diff options
929 files changed, 20045 insertions, 7350 deletions
diff --git a/apct-tests/perftests/core/src/android/graphics/perftests/CanvasPerfTest.java b/apct-tests/perftests/core/src/android/graphics/perftests/CanvasPerfTest.java index 3c361d772d3d..95730e836056 100644 --- a/apct-tests/perftests/core/src/android/graphics/perftests/CanvasPerfTest.java +++ b/apct-tests/perftests/core/src/android/graphics/perftests/CanvasPerfTest.java @@ -122,6 +122,8 @@ public class CanvasPerfTest { Bitmap.createScaledBitmap(source, source.getWidth() / 2, source.getHeight() / 2, true) .recycle(); } + source.recycle(); + Runtime.getRuntime().gc(); } @Test @@ -141,6 +143,8 @@ public class CanvasPerfTest { Bitmap.createScaledBitmap(source, source.getWidth() / 2, source.getHeight() / 2, true) .recycle(); } + source.recycle(); + Runtime.getRuntime().gc(); } @Test @@ -158,5 +162,7 @@ public class CanvasPerfTest { Bitmap.createScaledBitmap(source, source.getWidth() / 2, source.getHeight() / 2, true) .recycle(); } + source.recycle(); + Runtime.getRuntime().gc(); } } diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/FlexibilityController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/FlexibilityController.java index 44afbe6aff51..14cce19ef676 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/controllers/FlexibilityController.java +++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/FlexibilityController.java @@ -16,6 +16,11 @@ package com.android.server.job.controllers; +import static android.app.job.JobInfo.PRIORITY_DEFAULT; +import static android.app.job.JobInfo.PRIORITY_HIGH; +import static android.app.job.JobInfo.PRIORITY_LOW; +import static android.app.job.JobInfo.PRIORITY_MAX; +import static android.app.job.JobInfo.PRIORITY_MIN; import static android.text.format.DateUtils.DAY_IN_MILLIS; import static android.text.format.DateUtils.HOUR_IN_MILLIS; import static android.text.format.DateUtils.MINUTE_IN_MILLIS; @@ -43,9 +48,12 @@ import android.os.UserHandle; import android.provider.DeviceConfig; import android.util.ArraySet; import android.util.IndentingPrintWriter; +import android.util.KeyValueListParser; import android.util.Log; import android.util.Slog; +import android.util.SparseArray; import android.util.SparseArrayMap; +import android.util.SparseIntArray; import android.util.SparseLongArray; import android.util.TimeUtils; @@ -91,6 +99,23 @@ public final class FlexibilityController extends StateController { */ private long mFallbackFlexibilityDeadlineMs = FcConfig.DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_MS; + /** + * The default deadline that all flexible constraints should be dropped by if a job lacks + * a deadline, keyed by job priority. + */ + private SparseLongArray mFallbackFlexibilityDeadlines = + FcConfig.DEFAULT_FALLBACK_FLEXIBILITY_DEADLINES; + /** + * The scores to use for each job, keyed by job priority. + */ + private SparseIntArray mFallbackFlexibilityDeadlineScores = + FcConfig.DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_SCORES; + /** + * The amount of time to add (scaled by job run score) to the fallback flexibility deadline, + * keyed by job priority. + */ + private SparseLongArray mFallbackFlexibilityAdditionalScoreTimeFactors = + FcConfig.DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_ADDITIONAL_SCORE_TIME_FACTORS; private long mRescheduledJobDeadline = FcConfig.DEFAULT_RESCHEDULED_JOB_DEADLINE_MS; private long mMaxRescheduledDeadline = FcConfig.DEFAULT_MAX_RESCHEDULED_DEADLINE_MS; @@ -117,10 +142,10 @@ public final class FlexibilityController extends StateController { /** * The percent of a job's lifecycle to drop number of required constraints. - * mPercentToDropConstraints[i] denotes that at x% of a Jobs lifecycle, - * the controller should have i+1 constraints dropped. + * mPercentsToDropConstraints[i] denotes that at x% of a Jobs lifecycle, + * the controller should have i+1 constraints dropped. Keyed by job priority. */ - private int[] mPercentToDropConstraints; + private SparseArray<int[]> mPercentsToDropConstraints; /** * Keeps track of what flexible constraints are satisfied at the moment. @@ -199,6 +224,86 @@ public final class FlexibilityController extends StateController { } }; + /** Helper object to track job run score for each app. */ + private static class JobScoreTracker { + private static class JobScoreBucket { + @ElapsedRealtimeLong + public long startTimeElapsed; + public int score; + + private void reset() { + startTimeElapsed = 0; + score = 0; + } + } + + private static final int NUM_SCORE_BUCKETS = 24; + private static final long MAX_TIME_WINDOW_MS = 24 * HOUR_IN_MILLIS; + private final JobScoreBucket[] mScoreBuckets = new JobScoreBucket[NUM_SCORE_BUCKETS]; + private int mScoreBucketIndex = 0; + + public void addScore(int add, long nowElapsed) { + JobScoreBucket bucket = mScoreBuckets[mScoreBucketIndex]; + if (bucket == null) { + bucket = new JobScoreBucket(); + bucket.startTimeElapsed = nowElapsed; + mScoreBuckets[mScoreBucketIndex] = bucket; + } else if (bucket.startTimeElapsed < nowElapsed - MAX_TIME_WINDOW_MS) { + // The bucket is too old. + bucket.reset(); + bucket.startTimeElapsed = nowElapsed; + } else if (bucket.startTimeElapsed + < nowElapsed - MAX_TIME_WINDOW_MS / NUM_SCORE_BUCKETS) { + // The current bucket's duration has completed. Move on to the next bucket. + mScoreBucketIndex = (mScoreBucketIndex + 1) % NUM_SCORE_BUCKETS; + addScore(add, nowElapsed); + return; + } + + bucket.score += add; + } + + public int getScore(long nowElapsed) { + int score = 0; + final long earliestElapsed = nowElapsed - MAX_TIME_WINDOW_MS; + for (JobScoreBucket bucket : mScoreBuckets) { + if (bucket != null && bucket.startTimeElapsed >= earliestElapsed) { + score += bucket.score; + } + } + return score; + } + + public void dump(@NonNull IndentingPrintWriter pw, long nowElapsed) { + pw.print("{"); + + boolean printed = false; + for (int x = 0; x < mScoreBuckets.length; ++x) { + final int idx = (mScoreBucketIndex + 1 + x) % mScoreBuckets.length; + final JobScoreBucket jsb = mScoreBuckets[idx]; + if (jsb == null || jsb.startTimeElapsed == 0) { + continue; + } + if (printed) { + pw.print(", "); + } + TimeUtils.formatDuration(jsb.startTimeElapsed, nowElapsed, pw); + pw.print("="); + pw.print(jsb.score); + printed = true; + } + + pw.print("}"); + } + } + + /** + * Set of {@link JobScoreTracker JobScoreTrackers} for each app. + * Keyed by source UID -> source package. + **/ + private final SparseArrayMap<String, JobScoreTracker> mJobScoreTrackers = + new SparseArrayMap<>(); + private static final int MSG_CHECK_ALL_JOBS = 0; /** Check the jobs in {@link #mJobsToCheck} */ private static final int MSG_CHECK_JOBS = 1; @@ -228,8 +333,8 @@ public final class FlexibilityController extends StateController { mFcConfig = new FcConfig(); mFlexibilityAlarmQueue = new FlexibilityAlarmQueue( mContext, AppSchedulingModuleThread.get().getLooper()); - mPercentToDropConstraints = - mFcConfig.DEFAULT_PERCENT_TO_DROP_FLEXIBLE_CONSTRAINTS; + mPercentsToDropConstraints = + FcConfig.DEFAULT_PERCENTS_TO_DROP_FLEXIBLE_CONSTRAINTS; mPrefetchController = prefetchController; if (mFlexibilityEnabled) { @@ -272,6 +377,36 @@ public final class FlexibilityController extends StateController { } @Override + public void prepareForExecutionLocked(JobStatus jobStatus) { + // Use the job's requested priority to determine its score since that is what the developer + // selected and it will be stable across job runs. + final int score = mFallbackFlexibilityDeadlineScores + .get(jobStatus.getJob().getPriority(), jobStatus.getJob().getPriority() / 100); + JobScoreTracker jobScoreTracker = + mJobScoreTrackers.get(jobStatus.getSourceUid(), jobStatus.getSourcePackageName()); + if (jobScoreTracker == null) { + jobScoreTracker = new JobScoreTracker(); + mJobScoreTrackers.add(jobStatus.getSourceUid(), jobStatus.getSourcePackageName(), + jobScoreTracker); + } + jobScoreTracker.addScore(score, sElapsedRealtimeClock.millis()); + } + + @Override + public void unprepareFromExecutionLocked(JobStatus jobStatus) { + // The job didn't actually start. Undo the score increase. + JobScoreTracker jobScoreTracker = + mJobScoreTrackers.get(jobStatus.getSourceUid(), jobStatus.getSourcePackageName()); + if (jobScoreTracker == null) { + Slog.e(TAG, "Unprepared a job that didn't result in a score change"); + return; + } + final int score = mFallbackFlexibilityDeadlineScores + .get(jobStatus.getJob().getPriority(), jobStatus.getJob().getPriority() / 100); + jobScoreTracker.addScore(-score, sElapsedRealtimeClock.millis()); + } + + @Override @GuardedBy("mLock") public void maybeStopTrackingJobLocked(JobStatus js, JobStatus incomingJob) { if (js.clearTrackingController(JobStatus.TRACKING_FLEXIBILITY)) { @@ -286,12 +421,33 @@ public final class FlexibilityController extends StateController { public void onAppRemovedLocked(String packageName, int uid) { final int userId = UserHandle.getUserId(uid); mPrefetchLifeCycleStart.delete(userId, packageName); + mJobScoreTrackers.delete(uid, packageName); + for (int i = mJobsToCheck.size() - 1; i >= 0; --i) { + final JobStatus js = mJobsToCheck.valueAt(i); + if ((js.getSourceUid() == uid && js.getSourcePackageName().equals(packageName)) + || (js.getUid() == uid && js.getCallingPackageName().equals(packageName))) { + mJobsToCheck.removeAt(i); + } + } } @Override @GuardedBy("mLock") public void onUserRemovedLocked(int userId) { mPrefetchLifeCycleStart.delete(userId); + for (int u = mJobScoreTrackers.numMaps() - 1; u >= 0; --u) { + final int uid = mJobScoreTrackers.keyAt(u); + if (UserHandle.getUserId(uid) == userId) { + mJobScoreTrackers.deleteAt(u); + } + } + for (int i = mJobsToCheck.size() - 1; i >= 0; --i) { + final JobStatus js = mJobsToCheck.valueAt(i); + if (UserHandle.getUserId(js.getSourceUid()) == userId + || UserHandle.getUserId(js.getUid()) == userId) { + mJobsToCheck.removeAt(i); + } + } } boolean isEnabled() { @@ -308,9 +464,9 @@ public final class FlexibilityController extends StateController { || mService.getUidBias(js.getSourceUid()) == JobInfo.BIAS_TOP_APP // Only exclude DEFAULT+ priority jobs for BFGS+ apps || (mService.getUidBias(js.getSourceUid()) >= JobInfo.BIAS_BOUND_FOREGROUND_SERVICE - && js.getEffectivePriority() >= JobInfo.PRIORITY_DEFAULT) + && js.getEffectivePriority() >= PRIORITY_DEFAULT) // For apps in the power allowlist, automatically exclude DEFAULT+ priority jobs. - || (js.getEffectivePriority() >= JobInfo.PRIORITY_DEFAULT + || (js.getEffectivePriority() >= PRIORITY_DEFAULT && mPowerAllowlistedApps.contains(js.getSourcePackageName())) || hasEnoughSatisfiedConstraintsLocked(js) || mService.isCurrentlyRunningLocked(js); @@ -462,7 +618,14 @@ public final class FlexibilityController extends StateController { @VisibleForTesting @GuardedBy("mLock") - long getLifeCycleEndElapsedLocked(JobStatus js, long earliest) { + int getScoreLocked(int uid, @NonNull String pkgName, long nowElapsed) { + final JobScoreTracker scoreTracker = mJobScoreTrackers.get(uid, pkgName); + return scoreTracker == null ? 0 : scoreTracker.getScore(nowElapsed); + } + + @VisibleForTesting + @GuardedBy("mLock") + long getLifeCycleEndElapsedLocked(JobStatus js, long nowElapsed, long earliest) { if (js.getJob().isPrefetch()) { final long estimatedLaunchTime = mPrefetchController.getNextEstimatedLaunchTimeLocked(js); @@ -486,15 +649,28 @@ public final class FlexibilityController extends StateController { (long) Math.scalb(mRescheduledJobDeadline, js.getNumPreviousAttempts() - 2), mMaxRescheduledDeadline); } - return js.getLatestRunTimeElapsed() == JobStatus.NO_LATEST_RUNTIME - ? earliest + mFallbackFlexibilityDeadlineMs : js.getLatestRunTimeElapsed(); + if (js.getLatestRunTimeElapsed() == JobStatus.NO_LATEST_RUNTIME) { + // Intentionally use the effective priority here. If a job's priority was effectively + // lowered, it will be less likely to run quickly given other policies in JobScheduler. + // Thus, there's no need to further delay the job based on flex policy. + final int jobPriority = js.getEffectivePriority(); + final int jobScore = + getScoreLocked(js.getSourceUid(), js.getSourcePackageName(), nowElapsed); + // Set an upper limit on the fallback deadline so that the delay doesn't become extreme. + final long fallbackDeadlineMs = Math.min(3 * mFallbackFlexibilityDeadlineMs, + mFallbackFlexibilityDeadlines.get(jobPriority, mFallbackFlexibilityDeadlineMs) + + mFallbackFlexibilityAdditionalScoreTimeFactors + .get(jobPriority, MINUTE_IN_MILLIS) * jobScore); + return earliest + fallbackDeadlineMs; + } + return js.getLatestRunTimeElapsed(); } @VisibleForTesting @GuardedBy("mLock") int getCurPercentOfLifecycleLocked(JobStatus js, long nowElapsed) { final long earliest = getLifeCycleBeginningElapsedLocked(js); - final long latest = getLifeCycleEndElapsedLocked(js, earliest); + final long latest = getLifeCycleEndElapsedLocked(js, nowElapsed, earliest); if (latest == NO_LIFECYCLE_END || earliest >= nowElapsed) { return 0; } @@ -510,7 +686,8 @@ public final class FlexibilityController extends StateController { @GuardedBy("mLock") long getNextConstraintDropTimeElapsedLocked(JobStatus js) { final long earliest = getLifeCycleBeginningElapsedLocked(js); - final long latest = getLifeCycleEndElapsedLocked(js, earliest); + final long latest = + getLifeCycleEndElapsedLocked(js, sElapsedRealtimeClock.millis(), earliest); return getNextConstraintDropTimeElapsedLocked(js, earliest, latest); } @@ -518,15 +695,27 @@ public final class FlexibilityController extends StateController { @ElapsedRealtimeLong @GuardedBy("mLock") long getNextConstraintDropTimeElapsedLocked(JobStatus js, long earliest, long latest) { + final int[] percentsToDropConstraints = + getPercentsToDropConstraints(js.getEffectivePriority()); if (latest == NO_LIFECYCLE_END - || js.getNumDroppedFlexibleConstraints() == mPercentToDropConstraints.length) { + || js.getNumDroppedFlexibleConstraints() == percentsToDropConstraints.length) { return NO_LIFECYCLE_END; } - final int percent = mPercentToDropConstraints[js.getNumDroppedFlexibleConstraints()]; + final int percent = percentsToDropConstraints[js.getNumDroppedFlexibleConstraints()]; final long percentInTime = ((latest - earliest) * percent) / 100; return earliest + percentInTime; } + @NonNull + private int[] getPercentsToDropConstraints(int priority) { + int[] percentsToDropConstraints = mPercentsToDropConstraints.get(priority); + if (percentsToDropConstraints == null) { + Slog.wtf(TAG, "No %-to-drop for priority " + JobInfo.getPriorityString(priority)); + return new int[]{50, 60, 70, 80}; + } + return percentsToDropConstraints; + } + @Override @GuardedBy("mLock") public void onUidBiasChangedLocked(int uid, int prevBias, int newBias) { @@ -681,10 +870,12 @@ public final class FlexibilityController extends StateController { Integer.bitCount(getRelevantAppliedConstraintsLocked(js)); js.setNumAppliedFlexibleConstraints(numAppliedConstraints); + final int[] percentsToDropConstraints = + getPercentsToDropConstraints(js.getEffectivePriority()); final int curPercent = getCurPercentOfLifecycleLocked(js, nowElapsed); int toDrop = 0; for (int i = 0; i < numAppliedConstraints; i++) { - if (curPercent >= mPercentToDropConstraints[i]) { + if (curPercent >= percentsToDropConstraints[i]) { toDrop++; } } @@ -705,8 +896,10 @@ public final class FlexibilityController extends StateController { final int curPercent = getCurPercentOfLifecycleLocked(js, nowElapsed); int toDrop = 0; final int jsMaxFlexibleConstraints = js.getNumAppliedFlexibleConstraints(); + final int[] percentsToDropConstraints = + getPercentsToDropConstraints(js.getEffectivePriority()); for (int i = 0; i < jsMaxFlexibleConstraints; i++) { - if (curPercent >= mPercentToDropConstraints[i]) { + if (curPercent >= percentsToDropConstraints[i]) { toDrop++; } } @@ -733,7 +926,7 @@ public final class FlexibilityController extends StateController { return mTrackedJobs.size(); } - public void dump(IndentingPrintWriter pw, Predicate<JobStatus> predicate) { + public void dump(IndentingPrintWriter pw, Predicate<JobStatus> predicate, long nowElapsed) { for (int i = 0; i < mTrackedJobs.size(); i++) { ArraySet<JobStatus> jobs = mTrackedJobs.get(i); for (int j = 0; j < jobs.size(); j++) { @@ -744,8 +937,18 @@ public final class FlexibilityController extends StateController { js.printUniqueId(pw); pw.print(" from "); UserHandle.formatUid(pw, js.getSourceUid()); - pw.print(" Num Required Constraints: "); + pw.print("-> Num Required Constraints: "); pw.print(js.getNumRequiredFlexibleConstraints()); + + pw.print(", lifecycle=["); + final long earliest = getLifeCycleBeginningElapsedLocked(js); + pw.print(earliest); + pw.print(", ("); + pw.print(getCurPercentOfLifecycleLocked(js, nowElapsed)); + pw.print("%), "); + pw.print(getLifeCycleEndElapsedLocked(js, nowElapsed, earliest)); + pw.print("]"); + pw.println(); } } @@ -768,7 +971,7 @@ public final class FlexibilityController extends StateController { public void scheduleDropNumConstraintsAlarm(JobStatus js, long nowElapsed) { synchronized (mLock) { final long earliest = getLifeCycleBeginningElapsedLocked(js); - final long latest = getLifeCycleEndElapsedLocked(js, earliest); + final long latest = getLifeCycleEndElapsedLocked(js, nowElapsed, earliest); final long nextTimeElapsed = getNextConstraintDropTimeElapsedLocked(js, earliest, latest); @@ -936,10 +1139,16 @@ public final class FlexibilityController extends StateController { FC_CONFIG_PREFIX + "flexibility_deadline_proximity_limit_ms"; static final String KEY_FALLBACK_FLEXIBILITY_DEADLINE = FC_CONFIG_PREFIX + "fallback_flexibility_deadline_ms"; + static final String KEY_FALLBACK_FLEXIBILITY_DEADLINES = + FC_CONFIG_PREFIX + "fallback_flexibility_deadlines"; + static final String KEY_FALLBACK_FLEXIBILITY_DEADLINE_SCORES = + FC_CONFIG_PREFIX + "fallback_flexibility_deadline_scores"; + static final String KEY_FALLBACK_FLEXIBILITY_DEADLINE_ADDITIONAL_SCORE_TIME_FACTORS = + FC_CONFIG_PREFIX + "fallback_flexibility_deadline_additional_score_time_factors"; static final String KEY_MIN_TIME_BETWEEN_FLEXIBILITY_ALARMS_MS = FC_CONFIG_PREFIX + "min_time_between_flexibility_alarms_ms"; - static final String KEY_PERCENTS_TO_DROP_NUM_FLEXIBLE_CONSTRAINTS = - FC_CONFIG_PREFIX + "percents_to_drop_num_flexible_constraints"; + static final String KEY_PERCENTS_TO_DROP_FLEXIBLE_CONSTRAINTS = + FC_CONFIG_PREFIX + "percents_to_drop_flexible_constraints"; static final String KEY_MAX_RESCHEDULED_DEADLINE_MS = FC_CONFIG_PREFIX + "max_rescheduled_deadline_ms"; static final String KEY_RESCHEDULED_JOB_DEADLINE_MS = @@ -952,9 +1161,50 @@ public final class FlexibilityController extends StateController { static final long DEFAULT_DEADLINE_PROXIMITY_LIMIT_MS = 15 * MINUTE_IN_MILLIS; @VisibleForTesting static final long DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_MS = 24 * HOUR_IN_MILLIS; - private static final long DEFAULT_MIN_TIME_BETWEEN_FLEXIBILITY_ALARMS_MS = MINUTE_IN_MILLIS; + static final SparseLongArray DEFAULT_FALLBACK_FLEXIBILITY_DEADLINES = new SparseLongArray(); + static final SparseIntArray DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_SCORES = + new SparseIntArray(); + static final SparseLongArray + DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_ADDITIONAL_SCORE_TIME_FACTORS = + new SparseLongArray(); @VisibleForTesting - final int[] DEFAULT_PERCENT_TO_DROP_FLEXIBLE_CONSTRAINTS = {50, 60, 70, 80}; + static final SparseArray<int[]> DEFAULT_PERCENTS_TO_DROP_FLEXIBLE_CONSTRAINTS = + new SparseArray<>(); + + static { + DEFAULT_FALLBACK_FLEXIBILITY_DEADLINES.put(PRIORITY_MAX, HOUR_IN_MILLIS); + DEFAULT_FALLBACK_FLEXIBILITY_DEADLINES.put(PRIORITY_HIGH, 6 * HOUR_IN_MILLIS); + DEFAULT_FALLBACK_FLEXIBILITY_DEADLINES.put(PRIORITY_DEFAULT, 12 * HOUR_IN_MILLIS); + DEFAULT_FALLBACK_FLEXIBILITY_DEADLINES.put(PRIORITY_LOW, 24 * HOUR_IN_MILLIS); + DEFAULT_FALLBACK_FLEXIBILITY_DEADLINES.put(PRIORITY_MIN, 48 * HOUR_IN_MILLIS); + DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_SCORES.put(PRIORITY_MAX, 5); + DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_SCORES.put(PRIORITY_HIGH, 4); + DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_SCORES.put(PRIORITY_DEFAULT, 3); + DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_SCORES.put(PRIORITY_LOW, 2); + DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_SCORES.put(PRIORITY_MIN, 1); + DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_ADDITIONAL_SCORE_TIME_FACTORS + .put(PRIORITY_MAX, 0); + DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_ADDITIONAL_SCORE_TIME_FACTORS + .put(PRIORITY_HIGH, 4 * MINUTE_IN_MILLIS); + DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_ADDITIONAL_SCORE_TIME_FACTORS + .put(PRIORITY_DEFAULT, 3 * MINUTE_IN_MILLIS); + DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_ADDITIONAL_SCORE_TIME_FACTORS + .put(PRIORITY_LOW, 2 * MINUTE_IN_MILLIS); + DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_ADDITIONAL_SCORE_TIME_FACTORS + .put(PRIORITY_MIN, 1 * MINUTE_IN_MILLIS); + DEFAULT_PERCENTS_TO_DROP_FLEXIBLE_CONSTRAINTS + .put(PRIORITY_MAX, new int[]{1, 2, 3, 4}); + DEFAULT_PERCENTS_TO_DROP_FLEXIBLE_CONSTRAINTS + .put(PRIORITY_HIGH, new int[]{33, 50, 60, 75}); + DEFAULT_PERCENTS_TO_DROP_FLEXIBLE_CONSTRAINTS + .put(PRIORITY_DEFAULT, new int[]{50, 60, 70, 80}); + DEFAULT_PERCENTS_TO_DROP_FLEXIBLE_CONSTRAINTS + .put(PRIORITY_LOW, new int[]{50, 60, 70, 80}); + DEFAULT_PERCENTS_TO_DROP_FLEXIBLE_CONSTRAINTS + .put(PRIORITY_MIN, new int[]{55, 65, 75, 85}); + } + + private static final long DEFAULT_MIN_TIME_BETWEEN_FLEXIBILITY_ALARMS_MS = MINUTE_IN_MILLIS; private static final long DEFAULT_RESCHEDULED_JOB_DEADLINE_MS = HOUR_IN_MILLIS; private static final long DEFAULT_MAX_RESCHEDULED_DEADLINE_MS = 5 * DAY_IN_MILLIS; @VisibleForTesting @@ -968,9 +1218,11 @@ public final class FlexibilityController extends StateController { public long FALLBACK_FLEXIBILITY_DEADLINE_MS = DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_MS; public long MIN_TIME_BETWEEN_FLEXIBILITY_ALARMS_MS = DEFAULT_MIN_TIME_BETWEEN_FLEXIBILITY_ALARMS_MS; - /** The percentages of a jobs' lifecycle to drop the number of required constraints. */ - public int[] PERCENTS_TO_DROP_NUM_FLEXIBLE_CONSTRAINTS = - DEFAULT_PERCENT_TO_DROP_FLEXIBLE_CONSTRAINTS; + /** + * The percentages of a jobs' lifecycle to drop the number of required constraints. + * Keyed by job priority. + */ + public SparseArray<int[]> PERCENTS_TO_DROP_FLEXIBLE_CONSTRAINTS = new SparseArray<>(); /** Initial fallback flexible deadline for rescheduled jobs. */ public long RESCHEDULED_JOB_DEADLINE_MS = DEFAULT_RESCHEDULED_JOB_DEADLINE_MS; /** The max deadline for rescheduled jobs. */ @@ -980,10 +1232,56 @@ public final class FlexibilityController extends StateController { * it in order to run jobs. */ public long UNSEEN_CONSTRAINT_GRACE_PERIOD_MS = DEFAULT_UNSEEN_CONSTRAINT_GRACE_PERIOD_MS; + /** + * The base fallback deadlines to use if a job doesn't have its own deadline. Values are in + * milliseconds and keyed by job priority. + */ + public final SparseLongArray FALLBACK_FLEXIBILITY_DEADLINES = new SparseLongArray(); + /** + * The score to ascribe to each job, keyed by job priority. + */ + public final SparseIntArray FALLBACK_FLEXIBILITY_DEADLINE_SCORES = new SparseIntArray(); + /** + * How much additional time to increase the fallback deadline by based on the app's current + * job run score. Values are in + * milliseconds and keyed by job priority. + */ + public final SparseLongArray FALLBACK_FLEXIBILITY_DEADLINE_ADDITIONAL_SCORE_TIME_FACTORS = + new SparseLongArray(); + + FcConfig() { + // Copy the values from the DEFAULT_* data structures to avoid accidentally modifying + // the DEFAULT_* data structures in other parts of the code. + for (int i = 0; i < DEFAULT_FALLBACK_FLEXIBILITY_DEADLINES.size(); ++i) { + FALLBACK_FLEXIBILITY_DEADLINES.put( + DEFAULT_FALLBACK_FLEXIBILITY_DEADLINES.keyAt(i), + DEFAULT_FALLBACK_FLEXIBILITY_DEADLINES.valueAt(i)); + } + for (int i = 0; i < DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_SCORES.size(); ++i) { + FALLBACK_FLEXIBILITY_DEADLINE_SCORES.put( + DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_SCORES.keyAt(i), + DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_SCORES.valueAt(i)); + } + for (int i = 0; + i < DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_ADDITIONAL_SCORE_TIME_FACTORS.size(); + ++i) { + FALLBACK_FLEXIBILITY_DEADLINE_ADDITIONAL_SCORE_TIME_FACTORS.put( + DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_ADDITIONAL_SCORE_TIME_FACTORS + .keyAt(i), + DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_ADDITIONAL_SCORE_TIME_FACTORS + .valueAt(i)); + } + for (int i = 0; i < DEFAULT_PERCENTS_TO_DROP_FLEXIBLE_CONSTRAINTS.size(); ++i) { + PERCENTS_TO_DROP_FLEXIBLE_CONSTRAINTS.put( + DEFAULT_PERCENTS_TO_DROP_FLEXIBLE_CONSTRAINTS.keyAt(i), + DEFAULT_PERCENTS_TO_DROP_FLEXIBLE_CONSTRAINTS.valueAt(i)); + } + } @GuardedBy("mLock") public void processConstantLocked(@NonNull DeviceConfig.Properties properties, @NonNull String key) { + // TODO(257322915): add appropriate minimums and maximums to constants when parsing switch (key) { case KEY_APPLIED_CONSTRAINTS: APPLIED_CONSTRAINTS = @@ -1034,6 +1332,33 @@ public final class FlexibilityController extends StateController { properties.getLong(key, DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_MS); if (mFallbackFlexibilityDeadlineMs != FALLBACK_FLEXIBILITY_DEADLINE_MS) { mFallbackFlexibilityDeadlineMs = FALLBACK_FLEXIBILITY_DEADLINE_MS; + } + break; + case KEY_FALLBACK_FLEXIBILITY_DEADLINES: + if (parsePriorityToLongKeyValueString( + properties.getString(key, null), + FALLBACK_FLEXIBILITY_DEADLINES, + DEFAULT_FALLBACK_FLEXIBILITY_DEADLINES)) { + mFallbackFlexibilityDeadlines = FALLBACK_FLEXIBILITY_DEADLINES; + mShouldReevaluateConstraints = true; + } + break; + case KEY_FALLBACK_FLEXIBILITY_DEADLINE_SCORES: + if (parsePriorityToIntKeyValueString( + properties.getString(key, null), + FALLBACK_FLEXIBILITY_DEADLINE_SCORES, + DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_SCORES)) { + mFallbackFlexibilityDeadlineScores = FALLBACK_FLEXIBILITY_DEADLINE_SCORES; + mShouldReevaluateConstraints = true; + } + break; + case KEY_FALLBACK_FLEXIBILITY_DEADLINE_ADDITIONAL_SCORE_TIME_FACTORS: + if (parsePriorityToLongKeyValueString( + properties.getString(key, null), + FALLBACK_FLEXIBILITY_DEADLINE_ADDITIONAL_SCORE_TIME_FACTORS, + DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_ADDITIONAL_SCORE_TIME_FACTORS)) { + mFallbackFlexibilityAdditionalScoreTimeFactors = + FALLBACK_FLEXIBILITY_DEADLINE_ADDITIONAL_SCORE_TIME_FACTORS; mShouldReevaluateConstraints = true; } break; @@ -1056,25 +1381,69 @@ public final class FlexibilityController extends StateController { mShouldReevaluateConstraints = true; } break; - case KEY_PERCENTS_TO_DROP_NUM_FLEXIBLE_CONSTRAINTS: - String dropPercentString = properties.getString(key, ""); - PERCENTS_TO_DROP_NUM_FLEXIBLE_CONSTRAINTS = - parsePercentToDropString(dropPercentString); - if (PERCENTS_TO_DROP_NUM_FLEXIBLE_CONSTRAINTS != null - && !Arrays.equals(mPercentToDropConstraints, - PERCENTS_TO_DROP_NUM_FLEXIBLE_CONSTRAINTS)) { - mPercentToDropConstraints = PERCENTS_TO_DROP_NUM_FLEXIBLE_CONSTRAINTS; + case KEY_PERCENTS_TO_DROP_FLEXIBLE_CONSTRAINTS: + if (parsePercentToDropKeyValueString( + properties.getString(key, null), + PERCENTS_TO_DROP_FLEXIBLE_CONSTRAINTS, + DEFAULT_PERCENTS_TO_DROP_FLEXIBLE_CONSTRAINTS)) { + mPercentsToDropConstraints = PERCENTS_TO_DROP_FLEXIBLE_CONSTRAINTS; mShouldReevaluateConstraints = true; } break; } } - private int[] parsePercentToDropString(String s) { - String[] dropPercentString = s.split(","); + private boolean parsePercentToDropKeyValueString(@Nullable String s, + SparseArray<int[]> into, SparseArray<int[]> defaults) { + final KeyValueListParser priorityParser = new KeyValueListParser(','); + try { + priorityParser.setString(s); + } catch (IllegalArgumentException e) { + Slog.wtf(TAG, "Bad percent to drop key value string given", e); + // Clear the string and continue with the defaults. + priorityParser.setString(null); + } + + final int[] oldMax = into.get(PRIORITY_MAX); + final int[] oldHigh = into.get(PRIORITY_HIGH); + final int[] oldDefault = into.get(PRIORITY_DEFAULT); + final int[] oldLow = into.get(PRIORITY_LOW); + final int[] oldMin = into.get(PRIORITY_MIN); + + final int[] newMax = parsePercentToDropString(priorityParser.getString( + String.valueOf(PRIORITY_MAX), null)); + final int[] newHigh = parsePercentToDropString(priorityParser.getString( + String.valueOf(PRIORITY_HIGH), null)); + final int[] newDefault = parsePercentToDropString(priorityParser.getString( + String.valueOf(PRIORITY_DEFAULT), null)); + final int[] newLow = parsePercentToDropString(priorityParser.getString( + String.valueOf(PRIORITY_LOW), null)); + final int[] newMin = parsePercentToDropString(priorityParser.getString( + String.valueOf(PRIORITY_MIN), null)); + + into.put(PRIORITY_MAX, newMax == null ? defaults.get(PRIORITY_MAX) : newMax); + into.put(PRIORITY_HIGH, newHigh == null ? defaults.get(PRIORITY_HIGH) : newHigh); + into.put(PRIORITY_DEFAULT, + newDefault == null ? defaults.get(PRIORITY_DEFAULT) : newDefault); + into.put(PRIORITY_LOW, newLow == null ? defaults.get(PRIORITY_LOW) : newLow); + into.put(PRIORITY_MIN, newMin == null ? defaults.get(PRIORITY_MIN) : newMin); + + return !Arrays.equals(oldMax, into.get(PRIORITY_MAX)) + || !Arrays.equals(oldHigh, into.get(PRIORITY_HIGH)) + || !Arrays.equals(oldDefault, into.get(PRIORITY_DEFAULT)) + || !Arrays.equals(oldLow, into.get(PRIORITY_LOW)) + || !Arrays.equals(oldMin, into.get(PRIORITY_MIN)); + } + + @Nullable + private int[] parsePercentToDropString(@Nullable String s) { + if (s == null || s.isEmpty()) { + return null; + } + final String[] dropPercentString = s.split("\\|"); int[] dropPercentInt = new int[Integer.bitCount(FLEXIBLE_CONSTRAINTS)]; if (dropPercentInt.length != dropPercentString.length) { - return DEFAULT_PERCENT_TO_DROP_FLEXIBLE_CONSTRAINTS; + return null; } int prevPercent = 0; for (int i = 0; i < dropPercentString.length; i++) { @@ -1083,11 +1452,15 @@ public final class FlexibilityController extends StateController { Integer.parseInt(dropPercentString[i]); } catch (NumberFormatException ex) { Slog.e(TAG, "Provided string was improperly formatted.", ex); - return DEFAULT_PERCENT_TO_DROP_FLEXIBLE_CONSTRAINTS; + return null; } if (dropPercentInt[i] < prevPercent) { Slog.wtf(TAG, "Percents to drop constraints were not in increasing order."); - return DEFAULT_PERCENT_TO_DROP_FLEXIBLE_CONSTRAINTS; + return null; + } + if (dropPercentInt[i] > 100) { + Slog.e(TAG, "Found % over 100"); + return null; } prevPercent = dropPercentInt[i]; } @@ -1095,6 +1468,102 @@ public final class FlexibilityController extends StateController { return dropPercentInt; } + /** + * Parses the input string, expecting it to a key-value string where the keys are job + * priorities, and replaces everything in {@code into} with the values from the string, + * or the default values if the string contains none. + * + * Returns true if any values changed. + */ + private boolean parsePriorityToIntKeyValueString(@Nullable String s, + SparseIntArray into, SparseIntArray defaults) { + final KeyValueListParser parser = new KeyValueListParser(','); + try { + parser.setString(s); + } catch (IllegalArgumentException e) { + Slog.wtf(TAG, "Bad string given", e); + // Clear the string and continue with the defaults. + parser.setString(null); + } + + final int oldMax = into.get(PRIORITY_MAX); + final int oldHigh = into.get(PRIORITY_HIGH); + final int oldDefault = into.get(PRIORITY_DEFAULT); + final int oldLow = into.get(PRIORITY_LOW); + final int oldMin = into.get(PRIORITY_MIN); + + final int newMax = parser.getInt(String.valueOf(PRIORITY_MAX), + defaults.get(PRIORITY_MAX)); + final int newHigh = parser.getInt(String.valueOf(PRIORITY_HIGH), + defaults.get(PRIORITY_HIGH)); + final int newDefault = parser.getInt(String.valueOf(PRIORITY_DEFAULT), + defaults.get(PRIORITY_DEFAULT)); + final int newLow = parser.getInt(String.valueOf(PRIORITY_LOW), + defaults.get(PRIORITY_LOW)); + final int newMin = parser.getInt(String.valueOf(PRIORITY_MIN), + defaults.get(PRIORITY_MIN)); + + into.put(PRIORITY_MAX, newMax); + into.put(PRIORITY_HIGH, newHigh); + into.put(PRIORITY_DEFAULT, newDefault); + into.put(PRIORITY_LOW, newLow); + into.put(PRIORITY_MIN, newMin); + + return oldMax != newMax + || oldHigh != newHigh + || oldDefault != newDefault + || oldLow != newLow + || oldMin != newMin; + } + + /** + * Parses the input string, expecting it to a key-value string where the keys are job + * priorities, and replaces everything in {@code into} with the values from the string, + * or the default values if the string contains none. + * + * Returns true if any values changed. + */ + private boolean parsePriorityToLongKeyValueString(@Nullable String s, + SparseLongArray into, SparseLongArray defaults) { + final KeyValueListParser parser = new KeyValueListParser(','); + try { + parser.setString(s); + } catch (IllegalArgumentException e) { + Slog.wtf(TAG, "Bad string given", e); + // Clear the string and continue with the defaults. + parser.setString(null); + } + + final long oldMax = into.get(PRIORITY_MAX); + final long oldHigh = into.get(PRIORITY_HIGH); + final long oldDefault = into.get(PRIORITY_DEFAULT); + final long oldLow = into.get(PRIORITY_LOW); + final long oldMin = into.get(PRIORITY_MIN); + + final long newMax = parser.getLong(String.valueOf(PRIORITY_MAX), + defaults.get(PRIORITY_MAX)); + final long newHigh = parser.getLong(String.valueOf(PRIORITY_HIGH), + defaults.get(PRIORITY_HIGH)); + final long newDefault = parser.getLong(String.valueOf(PRIORITY_DEFAULT), + defaults.get(PRIORITY_DEFAULT)); + final long newLow = parser.getLong(String.valueOf(PRIORITY_LOW), + defaults.get(PRIORITY_LOW)); + final long newMin = parser.getLong(String.valueOf(PRIORITY_MIN), + defaults.get(PRIORITY_MIN)); + + into.put(PRIORITY_MAX, newMax); + into.put(PRIORITY_HIGH, newHigh); + into.put(PRIORITY_DEFAULT, newDefault); + into.put(PRIORITY_LOW, newLow); + into.put(PRIORITY_MIN, newMin); + + return oldMax != newMax + || oldHigh != newHigh + || oldDefault != newDefault + || oldLow != newLow + || oldMin != newMin; + } + private void dump(IndentingPrintWriter pw) { pw.println(); pw.print(FlexibilityController.class.getSimpleName()); @@ -1111,10 +1580,15 @@ public final class FlexibilityController extends StateController { pw.println(")"); pw.print(KEY_DEADLINE_PROXIMITY_LIMIT, DEADLINE_PROXIMITY_LIMIT_MS).println(); pw.print(KEY_FALLBACK_FLEXIBILITY_DEADLINE, FALLBACK_FLEXIBILITY_DEADLINE_MS).println(); + pw.print(KEY_FALLBACK_FLEXIBILITY_DEADLINES, FALLBACK_FLEXIBILITY_DEADLINES).println(); + pw.print(KEY_FALLBACK_FLEXIBILITY_DEADLINE_SCORES, + FALLBACK_FLEXIBILITY_DEADLINE_SCORES).println(); + pw.print(KEY_FALLBACK_FLEXIBILITY_DEADLINE_ADDITIONAL_SCORE_TIME_FACTORS, + FALLBACK_FLEXIBILITY_DEADLINE_ADDITIONAL_SCORE_TIME_FACTORS).println(); pw.print(KEY_MIN_TIME_BETWEEN_FLEXIBILITY_ALARMS_MS, MIN_TIME_BETWEEN_FLEXIBILITY_ALARMS_MS).println(); - pw.print(KEY_PERCENTS_TO_DROP_NUM_FLEXIBLE_CONSTRAINTS, - PERCENTS_TO_DROP_NUM_FLEXIBLE_CONSTRAINTS).println(); + pw.print(KEY_PERCENTS_TO_DROP_FLEXIBLE_CONSTRAINTS, + PERCENTS_TO_DROP_FLEXIBLE_CONSTRAINTS).println(); pw.print(KEY_RESCHEDULED_JOB_DEADLINE_MS, RESCHEDULED_JOB_DEADLINE_MS).println(); pw.print(KEY_MAX_RESCHEDULED_DEADLINE_MS, MAX_RESCHEDULED_DEADLINE_MS).println(); pw.print(KEY_UNSEEN_CONSTRAINT_GRACE_PERIOD_MS, UNSEEN_CONSTRAINT_GRACE_PERIOD_MS) @@ -1171,7 +1645,21 @@ public final class FlexibilityController extends StateController { pw.println(mPowerAllowlistedApps); pw.println(); - mFlexibilityTracker.dump(pw, predicate); + mFlexibilityTracker.dump(pw, predicate, nowElapsed); + + pw.println(); + pw.println("Job scores:"); + pw.increaseIndent(); + mJobScoreTrackers.forEach((uid, pkgName, jobScoreTracker) -> { + pw.print(uid); + pw.print("/"); + pw.print(pkgName); + pw.print(": "); + jobScoreTracker.dump(pw, nowElapsed); + pw.println(); + }); + pw.decreaseIndent(); + pw.println(); mFlexibilityAlarmQueue.dump(pw); } diff --git a/config/preloaded-classes b/config/preloaded-classes index c49971eb68ae..11b24f53ceaf 100644 --- a/config/preloaded-classes +++ b/config/preloaded-classes @@ -6172,8 +6172,6 @@ android.os.VibratorInfo$FrequencyProfile$1 android.os.VibratorInfo$FrequencyProfile android.os.VibratorInfo android.os.VibratorManager -android.os.VintfObject -android.os.VintfRuntimeInfo android.os.WorkSource$1 android.os.WorkSource$WorkChain$1 android.os.WorkSource$WorkChain diff --git a/core/api/current.txt b/core/api/current.txt index 865afc060736..4aa820a605b2 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -195,6 +195,7 @@ package android { field public static final String MANAGE_DEVICE_POLICY_SYSTEM_APPS = "android.permission.MANAGE_DEVICE_POLICY_SYSTEM_APPS"; field public static final String MANAGE_DEVICE_POLICY_SYSTEM_DIALOGS = "android.permission.MANAGE_DEVICE_POLICY_SYSTEM_DIALOGS"; field public static final String MANAGE_DEVICE_POLICY_SYSTEM_UPDATES = "android.permission.MANAGE_DEVICE_POLICY_SYSTEM_UPDATES"; + field @FlaggedApi("com.android.net.thread.flags.thread_user_restriction_enabled") public static final String MANAGE_DEVICE_POLICY_THREAD_NETWORK = "android.permission.MANAGE_DEVICE_POLICY_THREAD_NETWORK"; field public static final String MANAGE_DEVICE_POLICY_TIME = "android.permission.MANAGE_DEVICE_POLICY_TIME"; field public static final String MANAGE_DEVICE_POLICY_USB_DATA_SIGNALLING = "android.permission.MANAGE_DEVICE_POLICY_USB_DATA_SIGNALLING"; field public static final String MANAGE_DEVICE_POLICY_USB_FILE_TRANSFER = "android.permission.MANAGE_DEVICE_POLICY_USB_FILE_TRANSFER"; @@ -273,6 +274,7 @@ package android { field public static final String REQUEST_IGNORE_BATTERY_OPTIMIZATIONS = "android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"; field public static final String REQUEST_INSTALL_PACKAGES = "android.permission.REQUEST_INSTALL_PACKAGES"; field public static final String REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE = "android.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE"; + field @FlaggedApi("android.companion.flags.device_presence") public static final String REQUEST_OBSERVE_DEVICE_UUID_PRESENCE = "android.permission.REQUEST_OBSERVE_DEVICE_UUID_PRESENCE"; field public static final String REQUEST_PASSWORD_COMPLEXITY = "android.permission.REQUEST_PASSWORD_COMPLEXITY"; field @Deprecated public static final String RESTART_PACKAGES = "android.permission.RESTART_PACKAGES"; field public static final String RUN_USER_INITIATED_JOBS = "android.permission.RUN_USER_INITIATED_JOBS"; @@ -1602,6 +1604,7 @@ package android { field public static final int switchTextOff = 16843628; // 0x101036c field public static final int switchTextOn = 16843627; // 0x101036b field public static final int syncable = 16842777; // 0x1010019 + field @FlaggedApi("android.multiuser.enable_system_user_only_for_services_and_providers") public static final int systemUserOnly; field public static final int tabStripEnabled = 16843453; // 0x10102bd field public static final int tabStripLeft = 16843451; // 0x10102bb field public static final int tabStripRight = 16843452; // 0x10102bc @@ -9380,6 +9383,7 @@ package android.app.usage { method public long getBeginTimeMillis(); method public long getEndTimeMillis(); method @NonNull public int[] getEventTypes(); + method @NonNull public java.util.Set<java.lang.String> getPackageNames(); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.app.usage.UsageEventsQuery> CREATOR; } @@ -9388,6 +9392,7 @@ package android.app.usage { ctor public UsageEventsQuery.Builder(long, long); method @NonNull public android.app.usage.UsageEventsQuery build(); method @NonNull public android.app.usage.UsageEventsQuery.Builder setEventTypes(@NonNull int...); + method @NonNull public android.app.usage.UsageEventsQuery.Builder setPackageNames(@NonNull java.lang.String...); } public final class UsageStats implements android.os.Parcelable { @@ -9693,8 +9698,10 @@ package android.companion { method public void requestNotificationAccess(android.content.ComponentName); method @FlaggedApi("android.companion.association_tag") public void setAssociationTag(int, @NonNull String); method @RequiresPermission(android.Manifest.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE) public void startObservingDevicePresence(@NonNull String) throws android.companion.DeviceNotAssociatedException; + method @FlaggedApi("android.companion.device_presence") @RequiresPermission(android.Manifest.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE) public void startObservingDevicePresence(@NonNull android.companion.ObservingDevicePresenceRequest); method public void startSystemDataTransfer(int, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Void,android.companion.CompanionException>) throws android.companion.DeviceNotAssociatedException; method @RequiresPermission(android.Manifest.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE) public void stopObservingDevicePresence(@NonNull String) throws android.companion.DeviceNotAssociatedException; + method @FlaggedApi("android.companion.device_presence") @RequiresPermission(android.Manifest.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE) public void stopObservingDevicePresence(@NonNull android.companion.ObservingDevicePresenceRequest); field public static final String EXTRA_ASSOCIATION = "android.companion.extra.ASSOCIATION"; field @Deprecated public static final String EXTRA_DEVICE = "android.companion.extra.DEVICE"; field public static final int FLAG_CALL_METADATA = 1; // 0x1 @@ -9722,13 +9729,7 @@ package android.companion { method @MainThread public void onDeviceAppeared(@NonNull android.companion.AssociationInfo); method @Deprecated @MainThread public void onDeviceDisappeared(@NonNull String); method @MainThread public void onDeviceDisappeared(@NonNull android.companion.AssociationInfo); - method @FlaggedApi("android.companion.device_presence") @MainThread public void onDeviceEvent(@NonNull android.companion.AssociationInfo, int); - field @FlaggedApi("android.companion.device_presence") public static final int DEVICE_EVENT_BLE_APPEARED = 0; // 0x0 - field @FlaggedApi("android.companion.device_presence") public static final int DEVICE_EVENT_BLE_DISAPPEARED = 1; // 0x1 - field @FlaggedApi("android.companion.device_presence") public static final int DEVICE_EVENT_BT_CONNECTED = 2; // 0x2 - field @FlaggedApi("android.companion.device_presence") public static final int DEVICE_EVENT_BT_DISCONNECTED = 3; // 0x3 - field @FlaggedApi("android.companion.device_presence") public static final int DEVICE_EVENT_SELF_MANAGED_APPEARED = 4; // 0x4 - field @FlaggedApi("android.companion.device_presence") public static final int DEVICE_EVENT_SELF_MANAGED_DISAPPEARED = 5; // 0x5 + method @FlaggedApi("android.companion.device_presence") @MainThread public void onDevicePresenceEvent(@NonNull android.companion.DevicePresenceEvent); field public static final String SERVICE_INTERFACE = "android.companion.CompanionDeviceService"; } @@ -9741,6 +9742,38 @@ package android.companion { public class DeviceNotAssociatedException extends java.lang.RuntimeException { } + @FlaggedApi("android.companion.device_presence") public final class DevicePresenceEvent implements android.os.Parcelable { + ctor public DevicePresenceEvent(int, int, @Nullable android.os.ParcelUuid); + method public int describeContents(); + method public int getAssociationId(); + method public int getEvent(); + method @Nullable public android.os.ParcelUuid getUuid(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.companion.DevicePresenceEvent> CREATOR; + field public static final int EVENT_BLE_APPEARED = 0; // 0x0 + field public static final int EVENT_BLE_DISAPPEARED = 1; // 0x1 + field public static final int EVENT_BT_CONNECTED = 2; // 0x2 + field public static final int EVENT_BT_DISCONNECTED = 3; // 0x3 + field public static final int EVENT_SELF_MANAGED_APPEARED = 4; // 0x4 + field public static final int EVENT_SELF_MANAGED_DISAPPEARED = 5; // 0x5 + field public static final int NO_ASSOCIATION = -1; // 0xffffffff + } + + @FlaggedApi("android.companion.device_presence") public final class ObservingDevicePresenceRequest implements android.os.Parcelable { + method public int describeContents(); + method public int getAssociationId(); + method @Nullable public android.os.ParcelUuid getUuid(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.companion.ObservingDevicePresenceRequest> CREATOR; + } + + public static final class ObservingDevicePresenceRequest.Builder { + ctor public ObservingDevicePresenceRequest.Builder(); + method @NonNull public android.companion.ObservingDevicePresenceRequest build(); + method @NonNull public android.companion.ObservingDevicePresenceRequest.Builder setAssociationId(int); + method @NonNull @RequiresPermission(android.Manifest.permission.REQUEST_OBSERVE_DEVICE_UUID_PRESENCE) public android.companion.ObservingDevicePresenceRequest.Builder setUuid(@NonNull android.os.ParcelUuid); + } + public final class WifiDeviceFilter implements android.companion.DeviceFilter<android.net.wifi.ScanResult> { method public int describeContents(); method public void writeToParcel(@NonNull android.os.Parcel, int); @@ -12444,6 +12477,7 @@ package android.content.pm { method @NonNull public android.content.pm.PackageInstaller.Session openSession(int) throws java.io.IOException; method public void registerSessionCallback(@NonNull android.content.pm.PackageInstaller.SessionCallback); method public void registerSessionCallback(@NonNull android.content.pm.PackageInstaller.SessionCallback, @NonNull android.os.Handler); + method @FlaggedApi("android.content.pm.archiving") @RequiresPermission(anyOf={android.Manifest.permission.INSTALL_PACKAGES, android.Manifest.permission.REQUEST_INSTALL_PACKAGES}) public void reportUnarchivalState(@NonNull android.content.pm.PackageInstaller.UnarchivalState) throws android.content.pm.PackageManager.NameNotFoundException; method @FlaggedApi("android.content.pm.archiving") @RequiresPermission(anyOf={android.Manifest.permission.INSTALL_PACKAGES, android.Manifest.permission.REQUEST_INSTALL_PACKAGES}) public void reportUnarchivalStatus(int, int, long, @Nullable android.app.PendingIntent) throws android.content.pm.PackageManager.NameNotFoundException; method @FlaggedApi("android.content.pm.archiving") @RequiresPermission(anyOf={android.Manifest.permission.DELETE_PACKAGES, android.Manifest.permission.REQUEST_DELETE_PACKAGES}) public void requestArchive(@NonNull String, @NonNull android.content.IntentSender) throws android.content.pm.PackageManager.NameNotFoundException; method @FlaggedApi("android.content.pm.archiving") @RequiresPermission(anyOf={android.Manifest.permission.INSTALL_PACKAGES, android.Manifest.permission.REQUEST_INSTALL_PACKAGES}) public void requestUnarchive(@NonNull String, @NonNull android.content.IntentSender) throws java.io.IOException, android.content.pm.PackageManager.NameNotFoundException; @@ -12673,6 +12707,14 @@ package android.content.pm { field public static final int USER_ACTION_UNSPECIFIED = 0; // 0x0 } + @FlaggedApi("android.content.pm.archiving") public static final class PackageInstaller.UnarchivalState { + method @NonNull public static android.content.pm.PackageInstaller.UnarchivalState createGenericErrorState(int); + method @NonNull public static android.content.pm.PackageInstaller.UnarchivalState createInsufficientStorageState(int, long, @Nullable android.app.PendingIntent); + method @NonNull public static android.content.pm.PackageInstaller.UnarchivalState createNoConnectivityState(int); + method @NonNull public static android.content.pm.PackageInstaller.UnarchivalState createOkState(int); + method @NonNull public static android.content.pm.PackageInstaller.UnarchivalState createUserActionRequiredState(int, @NonNull android.app.PendingIntent); + } + public class PackageItemInfo { ctor public PackageItemInfo(); ctor public PackageItemInfo(android.content.pm.PackageItemInfo); @@ -17873,6 +17915,7 @@ package android.graphics.text { field public static final int HYPHENATION_FREQUENCY_FULL = 2; // 0x2 field public static final int HYPHENATION_FREQUENCY_NONE = 0; // 0x0 field public static final int HYPHENATION_FREQUENCY_NORMAL = 1; // 0x1 + field @FlaggedApi("com.android.text.flags.inter_character_justification") public static final int JUSTIFICATION_MODE_INTER_CHARACTER = 2; // 0x2 field public static final int JUSTIFICATION_MODE_INTER_WORD = 1; // 0x1 field public static final int JUSTIFICATION_MODE_NONE = 0; // 0x0 } @@ -18326,8 +18369,8 @@ package android.hardware { field public static final int RGBX_8888 = 2; // 0x2 field public static final int RGB_565 = 4; // 0x4 field public static final int RGB_888 = 3; // 0x3 - field @FlaggedApi("com.android.graphics.hwui.flags.requested_formats_v") public static final int RG_1616_UINT = 58; // 0x3a - field @FlaggedApi("com.android.graphics.hwui.flags.requested_formats_v") public static final int R_16_UINT = 57; // 0x39 + field @FlaggedApi("com.android.graphics.hwui.flags.requested_formats_v") public static final int RG_1616 = 58; // 0x3a + field @FlaggedApi("com.android.graphics.hwui.flags.requested_formats_v") public static final int R_16 = 57; // 0x39 field @FlaggedApi("com.android.graphics.hwui.flags.requested_formats_v") public static final int R_8 = 56; // 0x38 field public static final int S_UI8 = 53; // 0x35 field public static final long USAGE_COMPOSER_OVERLAY = 2048L; // 0x800L @@ -22151,16 +22194,17 @@ package android.media { method public void onJetUserIdUpdate(android.media.JetPlayer, int, int); } - @FlaggedApi("android.media.audio.loudness_configurator_api") public class LoudnessCodecConfigurator { + @FlaggedApi("android.media.audio.loudness_configurator_api") public class LoudnessCodecController implements java.lang.AutoCloseable { method @FlaggedApi("android.media.audio.loudness_configurator_api") public boolean addMediaCodec(@NonNull android.media.MediaCodec); - method @FlaggedApi("android.media.audio.loudness_configurator_api") @NonNull public static android.media.LoudnessCodecConfigurator create(); - method @FlaggedApi("android.media.audio.loudness_configurator_api") @NonNull public static android.media.LoudnessCodecConfigurator create(@NonNull java.util.concurrent.Executor, @NonNull android.media.LoudnessCodecConfigurator.OnLoudnessCodecUpdateListener); - method @FlaggedApi("android.media.audio.loudness_configurator_api") @NonNull public android.os.Bundle getLoudnessCodecParams(@NonNull android.media.AudioTrack, @NonNull android.media.MediaCodec); + method public void close(); + method @FlaggedApi("android.media.audio.loudness_configurator_api") @NonNull public static android.media.LoudnessCodecController create(int); + method @FlaggedApi("android.media.audio.loudness_configurator_api") @NonNull public static android.media.LoudnessCodecController create(int, @NonNull java.util.concurrent.Executor, @NonNull android.media.LoudnessCodecController.OnLoudnessCodecUpdateListener); + method @FlaggedApi("android.media.audio.loudness_configurator_api") @NonNull public android.os.Bundle getLoudnessCodecParams(@NonNull android.media.MediaCodec); + method @FlaggedApi("android.media.audio.loudness_configurator_api") public void release(); method @FlaggedApi("android.media.audio.loudness_configurator_api") public void removeMediaCodec(@NonNull android.media.MediaCodec); - method @FlaggedApi("android.media.audio.loudness_configurator_api") public void setAudioTrack(@Nullable android.media.AudioTrack); } - @FlaggedApi("android.media.audio.loudness_configurator_api") public static interface LoudnessCodecConfigurator.OnLoudnessCodecUpdateListener { + @FlaggedApi("android.media.audio.loudness_configurator_api") public static interface LoudnessCodecController.OnLoudnessCodecUpdateListener { method @FlaggedApi("android.media.audio.loudness_configurator_api") @NonNull public default android.os.Bundle onLoudnessCodecUpdate(@NonNull android.media.MediaCodec, @NonNull android.os.Bundle); } @@ -23314,6 +23358,8 @@ package android.media { field public static final String KEY_AUDIO_SESSION_ID = "audio-session-id"; field public static final String KEY_BITRATE_MODE = "bitrate-mode"; field public static final String KEY_BIT_RATE = "bitrate"; + field @FlaggedApi("com.android.media.codec.flags.large_audio_frame") public static final String KEY_BUFFER_BATCH_MAX_OUTPUT_SIZE = "buffer-batch-max-output-size"; + field @FlaggedApi("com.android.media.codec.flags.large_audio_frame") public static final String KEY_BUFFER_BATCH_THRESHOLD_OUTPUT_SIZE = "buffer-batch-threshold-output-size"; field public static final String KEY_CAPTION_SERVICE_NUMBER = "caption-service-number"; field public static final String KEY_CAPTURE_RATE = "capture-rate"; field public static final String KEY_CHANNEL_COUNT = "channel-count"; @@ -24254,7 +24300,7 @@ package android.media { method @Nullable public android.media.MediaRouter2.RoutingController getController(@NonNull String); method @NonNull public java.util.List<android.media.MediaRouter2.RoutingController> getControllers(); method @NonNull public static android.media.MediaRouter2 getInstance(@NonNull android.content.Context); - method @FlaggedApi("com.android.media.flags.enable_cross_user_routing_in_media_router2") @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MEDIA_CONTENT_CONTROL, android.Manifest.permission.MEDIA_ROUTING_CONTROL}) public static android.media.MediaRouter2 getInstance(@NonNull android.content.Context, @NonNull android.os.Looper, @NonNull String, @NonNull android.os.UserHandle); + method @FlaggedApi("com.android.media.flags.enable_cross_user_routing_in_media_router2") @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MEDIA_CONTENT_CONTROL, android.Manifest.permission.MEDIA_ROUTING_CONTROL}) public static android.media.MediaRouter2 getInstance(@NonNull android.content.Context, @NonNull String, @NonNull android.os.UserHandle); method @FlaggedApi("com.android.media.flags.enable_rlp_callbacks_in_media_router2") @Nullable public android.media.RouteListingPreference getRouteListingPreference(); method @NonNull public java.util.List<android.media.MediaRoute2Info> getRoutes(); method @NonNull public android.media.MediaRouter2.RoutingController getSystemController(); @@ -25470,34 +25516,34 @@ package android.media.audiofx { field public short preset; } - public class Virtualizer extends android.media.audiofx.AudioEffect { - ctor public Virtualizer(int, int) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.RuntimeException, java.lang.UnsupportedOperationException; - method public boolean canVirtualize(int, int) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException; - method public boolean forceVirtualizationMode(int) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException; - method public android.media.audiofx.Virtualizer.Settings getProperties() throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException; - method public short getRoundedStrength() throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException; - method public boolean getSpeakerAngles(int, int, int[]) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException; - method public boolean getStrengthSupported(); - method public int getVirtualizationMode() throws java.lang.IllegalStateException, java.lang.UnsupportedOperationException; - method public void setParameterListener(android.media.audiofx.Virtualizer.OnParameterChangeListener); - method public void setProperties(android.media.audiofx.Virtualizer.Settings) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException; - method public void setStrength(short) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException; - field public static final int PARAM_STRENGTH = 1; // 0x1 - field public static final int PARAM_STRENGTH_SUPPORTED = 0; // 0x0 - field public static final int VIRTUALIZATION_MODE_AUTO = 1; // 0x1 - field public static final int VIRTUALIZATION_MODE_BINAURAL = 2; // 0x2 - field public static final int VIRTUALIZATION_MODE_OFF = 0; // 0x0 - field public static final int VIRTUALIZATION_MODE_TRANSAURAL = 3; // 0x3 + @Deprecated public class Virtualizer extends android.media.audiofx.AudioEffect { + ctor @Deprecated public Virtualizer(int, int) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.RuntimeException, java.lang.UnsupportedOperationException; + method @Deprecated public boolean canVirtualize(int, int) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException; + method @Deprecated public boolean forceVirtualizationMode(int) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException; + method @Deprecated public android.media.audiofx.Virtualizer.Settings getProperties() throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException; + method @Deprecated public short getRoundedStrength() throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException; + method @Deprecated public boolean getSpeakerAngles(int, int, int[]) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException; + method @Deprecated public boolean getStrengthSupported(); + method @Deprecated public int getVirtualizationMode() throws java.lang.IllegalStateException, java.lang.UnsupportedOperationException; + method @Deprecated public void setParameterListener(android.media.audiofx.Virtualizer.OnParameterChangeListener); + method @Deprecated public void setProperties(android.media.audiofx.Virtualizer.Settings) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException; + method @Deprecated public void setStrength(short) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.UnsupportedOperationException; + field @Deprecated public static final int PARAM_STRENGTH = 1; // 0x1 + field @Deprecated public static final int PARAM_STRENGTH_SUPPORTED = 0; // 0x0 + field @Deprecated public static final int VIRTUALIZATION_MODE_AUTO = 1; // 0x1 + field @Deprecated public static final int VIRTUALIZATION_MODE_BINAURAL = 2; // 0x2 + field @Deprecated public static final int VIRTUALIZATION_MODE_OFF = 0; // 0x0 + field @Deprecated public static final int VIRTUALIZATION_MODE_TRANSAURAL = 3; // 0x3 } - public static interface Virtualizer.OnParameterChangeListener { - method public void onParameterChange(android.media.audiofx.Virtualizer, int, int, short); + @Deprecated public static interface Virtualizer.OnParameterChangeListener { + method @Deprecated public void onParameterChange(android.media.audiofx.Virtualizer, int, int, short); } - public static class Virtualizer.Settings { - ctor public Virtualizer.Settings(); - ctor public Virtualizer.Settings(String); - field public short strength; + @Deprecated public static class Virtualizer.Settings { + ctor @Deprecated public Virtualizer.Settings(); + ctor @Deprecated public Virtualizer.Settings(String); + field @Deprecated public short strength; } public class Visualizer { @@ -42216,9 +42262,11 @@ package android.telecom { method public android.graphics.drawable.Icon getIcon(); method public CharSequence getLabel(); method public CharSequence getShortDescription(); + method @FlaggedApi("com.android.internal.telephony.flags.simultaneous_calling_indications") @NonNull public java.util.Set<android.telecom.PhoneAccountHandle> getSimultaneousCallingRestriction(); method public android.net.Uri getSubscriptionAddress(); method public java.util.List<java.lang.String> getSupportedUriSchemes(); method public boolean hasCapabilities(int); + method @FlaggedApi("com.android.internal.telephony.flags.simultaneous_calling_indications") public boolean hasSimultaneousCallingRestriction(); method public boolean isEnabled(); method public boolean supportsUriScheme(String); method public android.telecom.PhoneAccount.Builder toBuilder(); @@ -42259,12 +42307,14 @@ package android.telecom { ctor public PhoneAccount.Builder(android.telecom.PhoneAccount); method public android.telecom.PhoneAccount.Builder addSupportedUriScheme(String); method public android.telecom.PhoneAccount build(); + method @FlaggedApi("com.android.internal.telephony.flags.simultaneous_calling_indications") @NonNull public android.telecom.PhoneAccount.Builder clearSimultaneousCallingRestriction(); method public android.telecom.PhoneAccount.Builder setAddress(android.net.Uri); method public android.telecom.PhoneAccount.Builder setCapabilities(int); method public android.telecom.PhoneAccount.Builder setExtras(android.os.Bundle); method public android.telecom.PhoneAccount.Builder setHighlightColor(int); method public android.telecom.PhoneAccount.Builder setIcon(android.graphics.drawable.Icon); method public android.telecom.PhoneAccount.Builder setShortDescription(CharSequence); + method @FlaggedApi("com.android.internal.telephony.flags.simultaneous_calling_indications") @NonNull public android.telecom.PhoneAccount.Builder setSimultaneousCallingRestriction(@NonNull java.util.Set<android.telecom.PhoneAccountHandle>); method public android.telecom.PhoneAccount.Builder setSubscriptionAddress(android.net.Uri); method public android.telecom.PhoneAccount.Builder setSupportedUriSchemes(java.util.List<java.lang.String>); } @@ -44942,7 +44992,7 @@ package android.telephony { method public void addOnSubscriptionsChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.SubscriptionManager.OnSubscriptionsChangedListener); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void addSubscriptionsIntoGroup(@NonNull java.util.List<java.lang.Integer>, @NonNull android.os.ParcelUuid); method public boolean canManageSubscription(android.telephony.SubscriptionInfo); - method @FlaggedApi("com.android.internal.telephony.flags.enforce_subscription_user_filter") @NonNull public android.telephony.SubscriptionManager createForAllUserProfiles(); + method @FlaggedApi("com.android.internal.telephony.flags.enforce_subscription_user_filter") @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_PROFILES) public android.telephony.SubscriptionManager createForAllUserProfiles(); method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public android.os.ParcelUuid createSubscriptionGroup(@NonNull java.util.List<java.lang.Integer>); method @Deprecated public static android.telephony.SubscriptionManager from(android.content.Context); method public java.util.List<android.telephony.SubscriptionInfo> getAccessibleSubscriptionInfoList(); @@ -46945,6 +46995,7 @@ package android.text { field @NonNull public static final android.text.Layout.TextInclusionStrategy INCLUSION_STRATEGY_ANY_OVERLAP; field @NonNull public static final android.text.Layout.TextInclusionStrategy INCLUSION_STRATEGY_CONTAINS_ALL; field @NonNull public static final android.text.Layout.TextInclusionStrategy INCLUSION_STRATEGY_CONTAINS_CENTER; + field @FlaggedApi("com.android.text.flags.inter_character_justification") public static final int JUSTIFICATION_MODE_INTER_CHARACTER = 2; // 0x2 field public static final int JUSTIFICATION_MODE_INTER_WORD = 1; // 0x1 field public static final int JUSTIFICATION_MODE_NONE = 0; // 0x0 } @@ -52413,9 +52464,9 @@ package android.view { field protected static final int[] PRESSED_STATE_SET; field protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET; field @FlaggedApi("android.view.flags.toolkit_set_frame_rate_read_only") public static final float REQUESTED_FRAME_RATE_CATEGORY_DEFAULT = 0.0f; - field @FlaggedApi("android.view.flags.toolkit_set_frame_rate_read_only") public static final float REQUESTED_FRAME_RATE_CATEGORY_HIGH = -120.0f; - field @FlaggedApi("android.view.flags.toolkit_set_frame_rate_read_only") public static final float REQUESTED_FRAME_RATE_CATEGORY_LOW = -30.0f; - field @FlaggedApi("android.view.flags.toolkit_set_frame_rate_read_only") public static final float REQUESTED_FRAME_RATE_CATEGORY_NORMAL = -60.0f; + field @FlaggedApi("android.view.flags.toolkit_set_frame_rate_read_only") public static final float REQUESTED_FRAME_RATE_CATEGORY_HIGH = -4.0f; + field @FlaggedApi("android.view.flags.toolkit_set_frame_rate_read_only") public static final float REQUESTED_FRAME_RATE_CATEGORY_LOW = -2.0f; + field @FlaggedApi("android.view.flags.toolkit_set_frame_rate_read_only") public static final float REQUESTED_FRAME_RATE_CATEGORY_NORMAL = -3.0f; field @FlaggedApi("android.view.flags.toolkit_set_frame_rate_read_only") public static final float REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE = -1.0f; field public static final android.util.Property<android.view.View,java.lang.Float> ROTATION; field public static final android.util.Property<android.view.View,java.lang.Float> ROTATION_X; @@ -57069,7 +57120,7 @@ package android.webkit { method public abstract boolean getBuiltInZoomControls(); method public abstract int getCacheMode(); method public abstract String getCursiveFontFamily(); - method @Deprecated public abstract boolean getDatabaseEnabled(); + method public abstract boolean getDatabaseEnabled(); method @Deprecated public abstract String getDatabasePath(); method public abstract int getDefaultFixedFontSize(); method public abstract int getDefaultFontSize(); @@ -57115,7 +57166,7 @@ package android.webkit { method public abstract void setBuiltInZoomControls(boolean); method public abstract void setCacheMode(int); method public abstract void setCursiveFontFamily(String); - method @Deprecated public abstract void setDatabaseEnabled(boolean); + method public abstract void setDatabaseEnabled(boolean); method @Deprecated public abstract void setDatabasePath(String); method public abstract void setDefaultFixedFontSize(int); method public abstract void setDefaultFontSize(int); diff --git a/core/api/system-current.txt b/core/api/system-current.txt index debf1bfdfc8c..318badfc8caa 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -56,7 +56,7 @@ package android { field public static final String BIND_CONTENT_SUGGESTIONS_SERVICE = "android.permission.BIND_CONTENT_SUGGESTIONS_SERVICE"; field public static final String BIND_DIRECTORY_SEARCH = "android.permission.BIND_DIRECTORY_SEARCH"; field public static final String BIND_DISPLAY_HASHING_SERVICE = "android.permission.BIND_DISPLAY_HASHING_SERVICE"; - field @FlaggedApi("com.android.internal.telephony.flags.ap_domain_selection_enabled") public static final String BIND_DOMAIN_SELECTION_SERVICE = "android.permission.BIND_DOMAIN_SELECTION_SERVICE"; + field @FlaggedApi("com.android.internal.telephony.flags.use_oem_domain_selection_service") public static final String BIND_DOMAIN_SELECTION_SERVICE = "android.permission.BIND_DOMAIN_SELECTION_SERVICE"; field public static final String BIND_DOMAIN_VERIFICATION_AGENT = "android.permission.BIND_DOMAIN_VERIFICATION_AGENT"; field public static final String BIND_EUICC_SERVICE = "android.permission.BIND_EUICC_SERVICE"; field public static final String BIND_EXTERNAL_STORAGE_SERVICE = "android.permission.BIND_EXTERNAL_STORAGE_SERVICE"; @@ -3959,6 +3959,7 @@ package android.content.pm { method public void setInstallAsInstantApp(boolean); method public void setInstallAsVirtualPreload(); method public void setRequestDowngrade(boolean); + method @FlaggedApi("android.content.pm.recoverability_detection") @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) public void setRollbackImpactLevel(int); method @FlaggedApi("android.content.pm.rollback_lifetime") @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) public void setRollbackLifetimeMillis(long); method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public void setStaged(); } @@ -4127,6 +4128,9 @@ package android.content.pm { field public static final int ROLLBACK_DATA_POLICY_RESTORE = 0; // 0x0 field public static final int ROLLBACK_DATA_POLICY_RETAIN = 2; // 0x2 field public static final int ROLLBACK_DATA_POLICY_WIPE = 1; // 0x1 + field @FlaggedApi("android.content.pm.recoverability_detection") public static final int ROLLBACK_USER_IMPACT_HIGH = 1; // 0x1 + field @FlaggedApi("android.content.pm.recoverability_detection") public static final int ROLLBACK_USER_IMPACT_LOW = 0; // 0x0 + field @FlaggedApi("android.content.pm.recoverability_detection") public static final int ROLLBACK_USER_IMPACT_ONLY_MANUAL = 2; // 0x2 field public static final int SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN = 0; // 0x0 field public static final int SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_VISIBLE = 1; // 0x1 field public static final int SYSTEM_APP_STATE_INSTALLED = 2; // 0x2 @@ -14712,7 +14716,7 @@ package android.telephony { method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getEmergencyNumberDbVersion(); method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getIsimDomain(); method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getIsimIst(); - method @FlaggedApi("com.android.server.telecom.flags.telecom_resolve_hidden_dependencies") @Nullable @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, "com.android.phone.permission.ACCESS_LAST_KNOWN_CELL_ID"}) public android.telephony.CellIdentity getLastKnownCellIdentity(); + method @FlaggedApi("com.android.server.telecom.flags.telecom_resolve_hidden_dependencies") @Nullable @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_LAST_KNOWN_CELL_ID}) public android.telephony.CellIdentity getLastKnownCellIdentity(); method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.Map<java.lang.Integer,java.lang.Integer> getLogicalToPhysicalSlotMapping(); method public int getMaxNumberOfSimultaneouslyActiveSims(); method public static long getMaxNumberVerificationTimeoutMillis(); diff --git a/core/api/test-current.txt b/core/api/test-current.txt index a866a34166f7..b8b98a3cb3ba 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -156,6 +156,7 @@ package android.app { field public static final int PROCESS_CAPABILITY_ALL_IMPLICIT = 6; // 0x6 field public static final int PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK = 8; // 0x8 field public static final int PROCESS_CAPABILITY_USER_RESTRICTED_NETWORK = 32; // 0x20 + field public static final int PROCESS_STATE_BOUND_FOREGROUND_SERVICE = 5; // 0x5 field public static final int PROCESS_STATE_FOREGROUND_SERVICE = 4; // 0x4 field public static final int PROCESS_STATE_TOP = 2; // 0x2 field public static final int STOP_USER_ON_SWITCH_DEFAULT = -1; // 0xffffffff @@ -376,6 +377,7 @@ package android.app { public class NotificationManager { method @FlaggedApi("android.app.modes_api") @NonNull public String addAutomaticZenRule(@NonNull android.app.AutomaticZenRule, boolean); method public void cleanUpCallersAfter(long); + method @FlaggedApi("android.app.modes_api") @NonNull public android.service.notification.ZenPolicy getDefaultZenPolicy(); method public android.content.ComponentName getEffectsSuppressor(); method public boolean isNotificationPolicyAccessGrantedForPackage(@NonNull String); method @FlaggedApi("android.app.modes_api") public boolean removeAutomaticZenRule(@NonNull String, boolean); @@ -1209,6 +1211,10 @@ package android.content.res { package android.content.rollback { + public final class RollbackInfo implements android.os.Parcelable { + method @FlaggedApi("android.content.pm.recoverability_detection") public int getRollbackImpactLevel(); + } + public final class RollbackManager { method @RequiresPermission(android.Manifest.permission.TEST_MANAGE_ROLLBACKS) public void blockRollbackManager(long); method @RequiresPermission(android.Manifest.permission.TEST_MANAGE_ROLLBACKS) public void expireRollbackForPackage(@NonNull String); @@ -3022,6 +3028,10 @@ package android.service.notification { method @Deprecated public boolean isBound(); } + public final class ZenPolicy implements android.os.Parcelable { + method @FlaggedApi("android.app.modes_api") @NonNull public android.service.notification.ZenPolicy overwrittenWith(@Nullable android.service.notification.ZenPolicy); + } + public static final class ZenPolicy.Builder { ctor public ZenPolicy.Builder(@Nullable android.service.notification.ZenPolicy); } diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index b2c64756e4bf..9d20f3c47bb5 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -712,6 +712,8 @@ public class ActivityManager { /** @hide Process is hosting a foreground service due to a system binding. */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @SuppressLint("UnflaggedApi") // @TestApi without associated feature. + @TestApi public static final int PROCESS_STATE_BOUND_FOREGROUND_SERVICE = ProcessStateEnum.BOUND_FOREGROUND_SERVICE; diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 949e2ba07a18..e288b42f7ec7 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -6834,23 +6834,24 @@ public final class ActivityThread extends ClientTransactionHandler PackageManager.GET_SHARED_LIBRARY_FILES, UserHandle.myUserId()); - if (mActivities.size() > 0) { - for (ActivityClientRecord ar : mActivities.values()) { - if (ar.activityInfo.applicationInfo.packageName - .equals(packageName)) { - ar.activityInfo.applicationInfo = aInfo; - ar.packageInfo = pkgInfo; + if (aInfo != null) { + if (mActivities.size() > 0) { + for (ActivityClientRecord ar : mActivities.values()) { + if (ar.activityInfo.applicationInfo.packageName + .equals(packageName)) { + ar.activityInfo.applicationInfo = aInfo; + ar.packageInfo = pkgInfo; + } } } - } - final String[] oldResDirs = { pkgInfo.getResDir() }; + final String[] oldResDirs = {pkgInfo.getResDir()}; - final ArrayList<String> oldPaths = new ArrayList<>(); - LoadedApk.makePaths(this, pkgInfo.getApplicationInfo(), oldPaths); - pkgInfo.updateApplicationInfo(aInfo, oldPaths); + final ArrayList<String> oldPaths = new ArrayList<>(); + LoadedApk.makePaths( + this, pkgInfo.getApplicationInfo(), oldPaths); + pkgInfo.updateApplicationInfo(aInfo, oldPaths); - synchronized (mResourcesManager) { // Update affected Resources objects to use new ResourcesImpl mResourcesManager.appendPendingAppInfoUpdate(oldResDirs, aInfo); diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index 4b2e93fda171..d8d136ae4df9 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -1533,10 +1533,11 @@ public class AppOpsManager { public static final int OP_RESERVED_FOR_TESTING = AppProtoEnums.APP_OP_RESERVED_FOR_TESTING; /** - * Rapid clearing of notifications by a notification listener, see b/289080543 for details + * Rapid clearing of notifications by a notification listener * * @hide */ + // See b/289080543 for more details public static final int OP_RAPID_CLEAR_NOTIFICATIONS_BY_LISTENER = AppProtoEnums.APP_OP_RAPID_CLEAR_NOTIFICATIONS_BY_LISTENER; @@ -2373,10 +2374,11 @@ public class AppOpsManager { "android:reserved_for_testing"; /** - * Rapid clearing of notifications by a notification listener, see b/289080543 for details + * Rapid clearing of notifications by a notification listener * * @hide */ + // See b/289080543 for more details @SystemApi @FlaggedApi(FLAG_RAPID_CLEAR_NOTIFICATIONS_BY_LISTENER_APP_OP_ENABLED) public static final String OPSTR_RAPID_CLEAR_NOTIFICATIONS_BY_LISTENER = diff --git a/core/java/android/app/ApplicationStartInfo.java b/core/java/android/app/ApplicationStartInfo.java index afa513dbaaef..c6712c044539 100644 --- a/core/java/android/app/ApplicationStartInfo.java +++ b/core/java/android/app/ApplicationStartInfo.java @@ -413,7 +413,9 @@ public final class ApplicationStartInfo implements Parcelable { * @hide */ public void setIntent(Intent startIntent) { - mStartIntent = startIntent; + if (startIntent != null) { + mStartIntent = startIntent.maybeStripForHistory(); + } } /** @@ -548,6 +550,8 @@ public final class ApplicationStartInfo implements Parcelable { /** * The intent used to launch the application. * + * <p class="note"> Note: Intent is stripped and does not include extras.</p> + * * <p class="note"> Note: field will be set for any {@link #getStartupState} value.</p> */ @SuppressLint("IntentBuilderName") @@ -662,6 +666,7 @@ public final class ApplicationStartInfo implements Parcelable { private static final String PROTO_SERIALIZER_ATTRIBUTE_TIMESTAMP = "timestamp"; private static final String PROTO_SERIALIZER_ATTRIBUTE_KEY = "key"; private static final String PROTO_SERIALIZER_ATTRIBUTE_TS = "ts"; + private static final String PROTO_SERIALIZER_ATTRIBUTE_INTENT = "intent"; /** * Write to a protocol buffer output stream. Protocol buffer message definition at {@link @@ -702,10 +707,17 @@ public final class ApplicationStartInfo implements Parcelable { } proto.write(ApplicationStartInfoProto.START_TYPE, mStartType); if (mStartIntent != null) { - Parcel parcel = Parcel.obtain(); - mStartIntent.writeToParcel(parcel, 0); - proto.write(ApplicationStartInfoProto.START_INTENT, parcel.marshall()); - parcel.recycle(); + ByteArrayOutputStream intentBytes = new ByteArrayOutputStream(); + ObjectOutputStream intentOut = new ObjectOutputStream(intentBytes); + TypedXmlSerializer serializer = Xml.resolveSerializer(intentOut); + serializer.startDocument(null, true); + serializer.startTag(null, PROTO_SERIALIZER_ATTRIBUTE_INTENT); + mStartIntent.saveToXml(serializer); + serializer.endTag(null, PROTO_SERIALIZER_ATTRIBUTE_INTENT); + serializer.endDocument(); + proto.write(ApplicationStartInfoProto.START_INTENT, + intentBytes.toByteArray()); + intentOut.close(); } proto.write(ApplicationStartInfoProto.LAUNCH_MODE, mLaunchMode); proto.end(token); @@ -772,15 +784,17 @@ public final class ApplicationStartInfo implements Parcelable { mStartType = proto.readInt(ApplicationStartInfoProto.START_TYPE); break; case (int) ApplicationStartInfoProto.START_INTENT: - byte[] startIntentBytes = proto.readBytes( - ApplicationStartInfoProto.START_INTENT); - if (startIntentBytes.length > 0) { - Parcel parcel = Parcel.obtain(); - parcel.unmarshall(startIntentBytes, 0, startIntentBytes.length); - parcel.setDataPosition(0); - mStartIntent = Intent.CREATOR.createFromParcel(parcel); - parcel.recycle(); + ByteArrayInputStream intentBytes = new ByteArrayInputStream(proto.readBytes( + ApplicationStartInfoProto.START_INTENT)); + ObjectInputStream intentIn = new ObjectInputStream(intentBytes); + try { + TypedXmlPullParser parser = Xml.resolvePullParser(intentIn); + XmlUtils.beginDocument(parser, PROTO_SERIALIZER_ATTRIBUTE_INTENT); + mStartIntent = Intent.restoreFromXml(parser); + } catch (XmlPullParserException e) { + // Intent lost } + intentIn.close(); break; case (int) ApplicationStartInfoProto.LAUNCH_MODE: mLaunchMode = proto.readInt(ApplicationStartInfoProto.LAUNCH_MODE); diff --git a/core/java/android/app/IActivityClientController.aidl b/core/java/android/app/IActivityClientController.aidl index 7370fc36c23e..5b044f616487 100644 --- a/core/java/android/app/IActivityClientController.aidl +++ b/core/java/android/app/IActivityClientController.aidl @@ -119,7 +119,7 @@ interface IActivityClientController { oneway void setShowWhenLocked(in IBinder token, boolean showWhenLocked); oneway void setInheritShowWhenLocked(in IBinder token, boolean setInheritShownWhenLocked); - oneway void setTurnScreenOn(in IBinder token, boolean turnScreenOn); + void setTurnScreenOn(in IBinder token, boolean turnScreenOn); oneway void setAllowCrossUidActivitySwitchFromBelow(in IBinder token, boolean allowed); oneway void reportActivityFullyDrawn(in IBinder token, boolean restoredFromBundle); oneway void overrideActivityTransition(IBinder token, boolean open, int enterAnim, int exitAnim, diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl index c3adbc30641f..578105f9f99e 100644 --- a/core/java/android/app/INotificationManager.aidl +++ b/core/java/android/app/INotificationManager.aidl @@ -38,6 +38,7 @@ import android.service.notification.IConditionProvider; import android.service.notification.INotificationListener; import android.service.notification.NotificationListenerFilter; import android.service.notification.StatusBarNotification; +import android.service.notification.ZenPolicy; import android.app.AutomaticZenRule; import android.service.notification.ZenModeConfig; @@ -213,6 +214,7 @@ interface INotificationManager boolean isNotificationPolicyAccessGrantedForPackage(String pkg); void setNotificationPolicyAccessGranted(String pkg, boolean granted); void setNotificationPolicyAccessGrantedForUser(String pkg, int userId, boolean granted); + ZenPolicy getDefaultZenPolicy(); AutomaticZenRule getAutomaticZenRule(String id); Map<String, AutomaticZenRule> getAutomaticZenRules(); // TODO: b/310620812 - Remove getZenRules() when MODES_API is inlined. diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java index 0b6e24cf5545..366b45badcfd 100644 --- a/core/java/android/app/NotificationManager.java +++ b/core/java/android/app/NotificationManager.java @@ -1750,6 +1750,20 @@ public class NotificationManager { @NonNull ComponentName listener, boolean granted) { setNotificationListenerAccessGranted(listener, granted, true); } + /** + * Gets the device-default notification policy as a ZenPolicy. + * @hide + */ + @TestApi + @FlaggedApi(Flags.FLAG_MODES_API) + public @NonNull ZenPolicy getDefaultZenPolicy() { + INotificationManager service = getService(); + try { + return service.getDefaultZenPolicy(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } /** * For apps targeting {@link Build.VERSION_CODES#VANILLA_ICE_CREAM} and above, the diff --git a/core/java/android/app/OWNERS b/core/java/android/app/OWNERS index 47d19eda0c72..0760d4db9169 100644 --- a/core/java/android/app/OWNERS +++ b/core/java/android/app/OWNERS @@ -57,6 +57,7 @@ per-file ReceiverInfo* = file:/BROADCASTS_OWNERS # GrammaticalInflectionManager per-file *GrammaticalInflection* = file:/services/core/java/com/android/server/grammaticalinflection/OWNERS +per-file grammatical_inflection_manager.aconfig = file:/services/core/java/com/android/server/grammaticalinflection/OWNERS # KeyguardManager per-file KeyguardManager.java = file:/services/core/java/com/android/server/locksettings/OWNERS diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java index 63f37f150d33..36b03c1b1f48 100644 --- a/core/java/android/app/WallpaperManager.java +++ b/core/java/android/app/WallpaperManager.java @@ -261,6 +261,13 @@ public class WallpaperManager { public static final String COMMAND_GOING_TO_SLEEP = "android.wallpaper.goingtosleep"; /** + * Command for {@link #sendWallpaperCommand}: reported when a physical display switch event + * happens, e.g. fold and unfold. + * @hide + */ + public static final String COMMAND_DISPLAY_SWITCH = "android.wallpaper.displayswitch"; + + /** * Command for {@link #sendWallpaperCommand}: reported when the wallpaper that was already * set is re-applied by the user. * @hide diff --git a/core/java/android/app/admin/flags/flags.aconfig b/core/java/android/app/admin/flags/flags.aconfig index 35ce10223aa6..b3ecd92c56c9 100644 --- a/core/java/android/app/admin/flags/flags.aconfig +++ b/core/java/android/app/admin/flags/flags.aconfig @@ -55,3 +55,10 @@ flag { description: "Guards a bugfix that ends the credential input flow if the managed user has not stopped." bug: "293441361" } + +flag { + name: "default_sms_personal_app_suspension_fix_enabled" + namespace: "enterprise" + description: "Exempt the default sms app of the context user for suspension when calling setPersonalAppsSuspended" + bug: "309183330" +} diff --git a/core/java/android/app/background_install_control_manager.aconfig b/core/java/android/app/background_install_control_manager.aconfig new file mode 100644 index 000000000000..029b93ab4534 --- /dev/null +++ b/core/java/android/app/background_install_control_manager.aconfig @@ -0,0 +1,9 @@ +package: "android.app" + +flag { + namespace: "background_install_control" + name: "bic_client" + description: "System API for background install control." + is_fixed_read_only: true + bug: "287507984" +} diff --git a/core/java/android/app/backup/BackupHelperWithLogger.java b/core/java/android/app/backup/BackupHelperWithLogger.java new file mode 100644 index 000000000000..1a59a5302f07 --- /dev/null +++ b/core/java/android/app/backup/BackupHelperWithLogger.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.app.backup; + +import android.os.ParcelFileDescriptor; + +/** + * Utility class for writing BackupHelpers with added logging capabilities. + * Used for passing a logger object to Helper in key shared backup agents + * + * @hide + */ +public abstract class BackupHelperWithLogger implements BackupHelper { + private BackupRestoreEventLogger mLogger; + private boolean mIsLoggerSet = false; + + public abstract void writeNewStateDescription(ParcelFileDescriptor newState); + + public abstract void restoreEntity(BackupDataInputStream data); + + public abstract void performBackup(ParcelFileDescriptor oldState, BackupDataOutput data, + ParcelFileDescriptor newState); + + /** + * Gets the logger so that the backuphelper can log success/error for each datatype handled + */ + public BackupRestoreEventLogger getLogger() { + return mLogger; + } + + /** + * Allow the shared backup agent to pass a logger to each of its backup helper + */ + public void setLogger(BackupRestoreEventLogger logger) { + mLogger = logger; + mIsLoggerSet = true; + } + + /** + * Allow the helper to check if its shared backup agent has passed a logger + */ + public boolean isLoggerSet() { + return mIsLoggerSet; + } +} diff --git a/core/java/android/app/backup/BlobBackupHelper.java b/core/java/android/app/backup/BlobBackupHelper.java index 82d0a94ce0da..a55ff4899296 100644 --- a/core/java/android/app/backup/BlobBackupHelper.java +++ b/core/java/android/app/backup/BlobBackupHelper.java @@ -39,7 +39,7 @@ import java.util.zip.InflaterInputStream; * * @hide */ -public abstract class BlobBackupHelper implements BackupHelper { +public abstract class BlobBackupHelper extends BackupHelperWithLogger { private static final String TAG = "BlobBackupHelper"; private static final boolean DEBUG = false; diff --git a/core/java/android/app/usage/UsageEventsQuery.java b/core/java/android/app/usage/UsageEventsQuery.java index df6324f744a8..c0f13ca557e2 100644 --- a/core/java/android/app/usage/UsageEventsQuery.java +++ b/core/java/android/app/usage/UsageEventsQuery.java @@ -24,11 +24,15 @@ import android.app.usage.UsageEvents.Event; import android.os.Parcel; import android.os.Parcelable; import android.os.UserHandle; +import android.text.TextUtils; import android.util.ArraySet; import com.android.internal.util.ArrayUtils; import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; /** * An Object-Oriented representation for a {@link UsageEvents} query. @@ -40,12 +44,14 @@ public final class UsageEventsQuery implements Parcelable { private final @CurrentTimeMillisLong long mEndTimeMillis; private final @Event.EventType int[] mEventTypes; private final @UserIdInt int mUserId; + private final String[] mPackageNames; private UsageEventsQuery(@NonNull Builder builder) { mBeginTimeMillis = builder.mBeginTimeMillis; mEndTimeMillis = builder.mEndTimeMillis; mEventTypes = ArrayUtils.convertToIntArray(builder.mEventTypes); mUserId = builder.mUserId; + mPackageNames = builder.mPackageNames.toArray(new String[builder.mPackageNames.size()]); } private UsageEventsQuery(Parcel in) { @@ -55,6 +61,9 @@ public final class UsageEventsQuery implements Parcelable { mEventTypes = new int[eventTypesLength]; in.readIntArray(mEventTypes); mUserId = in.readInt(); + int packageNamesLength = in.readInt(); + mPackageNames = new String[packageNamesLength]; + in.readStringArray(mPackageNames); } /** @@ -92,6 +101,28 @@ public final class UsageEventsQuery implements Parcelable { return mUserId; } + /** + * Retrieves a {@code Set} of package names for the query. + * <p>Note that an empty set indicates querying usage events for all packages, and + * it may cause additional system overhead when calling + * {@link UsageStatsManager#queryEvents(UsageEventsQuery)}. Apps are encouraged to + * provide a list of package names via {@link Builder#setPackageNames(String...)}</p> + * + * @return a {@code Set} contains the package names that was previously set through + * {@link Builder#setPackageNames(String...)} or an empty set if no value has been set. + */ + public @NonNull Set<String> getPackageNames() { + if (ArrayUtils.isEmpty(mPackageNames)) { + return Collections.emptySet(); + } + + final HashSet<String> pkgNameSet = new HashSet<>(); + for (String pkgName: mPackageNames) { + pkgNameSet.add(pkgName); + } + return pkgNameSet; + } + @Override public int describeContents() { return 0; @@ -104,6 +135,8 @@ public final class UsageEventsQuery implements Parcelable { dest.writeInt(mEventTypes.length); dest.writeIntArray(mEventTypes); dest.writeInt(mUserId); + dest.writeInt(mPackageNames.length); + dest.writeStringArray(mPackageNames); } @NonNull @@ -128,6 +161,7 @@ public final class UsageEventsQuery implements Parcelable { private final @CurrentTimeMillisLong long mEndTimeMillis; private final ArraySet<Integer> mEventTypes = new ArraySet<>(); private @UserIdInt int mUserId = UserHandle.USER_NULL; + private final ArraySet<String> mPackageNames = new ArraySet<>(); /** * Constructor that specifies the period for which to return events. @@ -194,5 +228,33 @@ public final class UsageEventsQuery implements Parcelable { mUserId = userId; return this; } + + /** + * Sets the list of package names to be included in the query. + * + * <p>Note: </p> An empty {@code Set} will be returned by + * {@link UsageEventsQuery#getPackageNames()} without calling this method, which indicates + * querying usage events for all packages. Apps are encouraged to provide a list of package + * names. Only the matching names supplied will be used to query. + * + * @param pkgNames the array of the package names, each package name should be a non-empty + * string, {@code null} or empty string("") is omitted. + * @see UsageEventsQuery#getPackageNames() + * @see UsageStatsManager#queryEvents(UsageEventsQuery) + * @throws NullPointerException if {@code pkgNames} is {@code null} or empty. + */ + public @NonNull Builder setPackageNames(@NonNull String... pkgNames) { + if (pkgNames == null || pkgNames.length == 0) { + throw new NullPointerException("pkgNames is null or empty"); + } + mPackageNames.clear(); + for (int i = 0; i < pkgNames.length; i++) { + if (!TextUtils.isEmpty(pkgNames[i])) { + mPackageNames.add(pkgNames[i]); + } + } + + return this; + } } } diff --git a/core/java/android/companion/CompanionDeviceManager.java b/core/java/android/companion/CompanionDeviceManager.java index 672e343959cb..d74399274a60 100644 --- a/core/java/android/companion/CompanionDeviceManager.java +++ b/core/java/android/companion/CompanionDeviceManager.java @@ -1038,6 +1038,7 @@ public final class CompanionDeviceManager { } } + // TODO(b/315163162) Add @Deprecated keyword after 24Q2 cut. /** * Register to receive callbacks whenever the associated device comes in and out of range. * @@ -1094,7 +1095,7 @@ public final class CompanionDeviceManager { callingUid, callingPid); } } - + // TODO(b/315163162) Add @Deprecated keyword after 24Q2 cut. /** * Unregister for receiving callbacks whenever the associated device comes in and out of range. * @@ -1137,6 +1138,64 @@ public final class CompanionDeviceManager { } /** + * Register to receive callbacks whenever the associated device comes in and out of range. + * + * <p>The app doesn't need to remain running in order to receive its callbacks.</p> + * + * <p>Calling app must check for feature presence of + * {@link PackageManager#FEATURE_COMPANION_DEVICE_SETUP} before calling this API.</p> + * + * <p>For Bluetooth LE devices, this is based on scanning for device with the given address. + * The system will scan for the device when Bluetooth is ON or Bluetooth scanning is ON.</p> + * + * <p>For Bluetooth classic devices this is triggered when the device connects/disconnects.</p> + * + * <p>WiFi devices are not supported.</p> + * + * <p>If a Bluetooth LE device wants to use a rotating mac address, it is recommended to use + * Resolvable Private Address, and ensure the device is bonded to the phone so that android OS + * is able to resolve the address.</p> + * + * @param request A request for setting the types of device for observing device presence. + * + * @see ObservingDevicePresenceRequest.Builder + * @see CompanionDeviceService#onDevicePresenceEvent(DevicePresenceEvent) + */ + @FlaggedApi(Flags.FLAG_DEVICE_PRESENCE) + @RequiresPermission(android.Manifest.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE) + public void startObservingDevicePresence(@NonNull ObservingDevicePresenceRequest request) { + Objects.requireNonNull(request, "request cannot be null"); + + try { + mService.startObservingDevicePresence( + request, mContext.getOpPackageName(), mContext.getUserId()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Unregister for receiving callbacks whenever the associated device comes in and out of range. + * + * Calling app must check for feature presence of + * {@link PackageManager#FEATURE_COMPANION_DEVICE_SETUP} before calling this API. + * + * @param request A request for setting the types of device for observing device presence. + */ + @FlaggedApi(Flags.FLAG_DEVICE_PRESENCE) + @RequiresPermission(android.Manifest.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE) + public void stopObservingDevicePresence(@NonNull ObservingDevicePresenceRequest request) { + Objects.requireNonNull(request, "request cannot be null"); + + try { + mService.stopObservingDevicePresence( + request, mContext.getOpPackageName(), mContext.getUserId()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** * Dispatch a message to system for processing. It should only be called by * {@link CompanionDeviceService#dispatchMessageToSystem(int, int, byte[])} * diff --git a/core/java/android/companion/CompanionDeviceService.java b/core/java/android/companion/CompanionDeviceService.java index 4d0267ca0cbb..5ad2348254e2 100644 --- a/core/java/android/companion/CompanionDeviceService.java +++ b/core/java/android/companion/CompanionDeviceService.java @@ -18,7 +18,6 @@ package android.companion; import android.annotation.FlaggedApi; -import android.annotation.IntDef; import android.annotation.MainThread; import android.annotation.NonNull; import android.annotation.Nullable; @@ -33,8 +32,6 @@ import android.util.Log; import java.io.InputStream; import java.io.OutputStream; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; import java.util.Objects; import java.util.concurrent.Executor; @@ -123,62 +120,6 @@ public abstract class CompanionDeviceService extends Service { */ public static final String SERVICE_INTERFACE = "android.companion.CompanionDeviceService"; - /** @hide */ - @IntDef(prefix = {"DEVICE_EVENT"}, value = { - DEVICE_EVENT_BLE_APPEARED, - DEVICE_EVENT_BLE_DISAPPEARED, - DEVICE_EVENT_BT_CONNECTED, - DEVICE_EVENT_BT_DISCONNECTED, - DEVICE_EVENT_SELF_MANAGED_APPEARED, - DEVICE_EVENT_SELF_MANAGED_DISAPPEARED - }) - - @Retention(RetentionPolicy.SOURCE) - public @interface DeviceEvent {} - - /** - * Companion app receives {@link #onDeviceEvent(AssociationInfo, int)} callback - * with this event if the device comes into BLE range. - */ - @FlaggedApi(Flags.FLAG_DEVICE_PRESENCE) - public static final int DEVICE_EVENT_BLE_APPEARED = 0; - - /** - * Companion app receives {@link #onDeviceEvent(AssociationInfo, int)} callback - * with this event if the device is no longer in BLE range. - */ - @FlaggedApi(Flags.FLAG_DEVICE_PRESENCE) - public static final int DEVICE_EVENT_BLE_DISAPPEARED = 1; - - /** - * Companion app receives {@link #onDeviceEvent(AssociationInfo, int)} callback - * with this event when the bluetooth device is connected. - */ - @FlaggedApi(Flags.FLAG_DEVICE_PRESENCE) - public static final int DEVICE_EVENT_BT_CONNECTED = 2; - - /** - * Companion app receives {@link #onDeviceEvent(AssociationInfo, int)} callback - * with this event if the bluetooth device is disconnected. - */ - @FlaggedApi(Flags.FLAG_DEVICE_PRESENCE) - public static final int DEVICE_EVENT_BT_DISCONNECTED = 3; - - /** - * A companion app for a self-managed device will receive the callback - * {@link #onDeviceEvent(AssociationInfo, int)} if it reports that a device has appeared on its - * own. - */ - @FlaggedApi(Flags.FLAG_DEVICE_PRESENCE) - public static final int DEVICE_EVENT_SELF_MANAGED_APPEARED = 4; - - /** - * A companion app for a self-managed device will receive the callback - * {@link #onDeviceEvent(AssociationInfo, int)} if it reports that a device has disappeared on - * its own. - */ - @FlaggedApi(Flags.FLAG_DEVICE_PRESENCE) - public static final int DEVICE_EVENT_SELF_MANAGED_DISAPPEARED = 5; private final Stub mRemote = new Stub(); @@ -306,6 +247,7 @@ public abstract class CompanionDeviceService extends Service { .detachSystemDataTransport(associationId); } + // TODO(b/315163162) Add @Deprecated keyword after 24Q2 cut. /** * Called by system whenever a device associated with this app is connected. * @@ -318,6 +260,7 @@ public abstract class CompanionDeviceService extends Service { } } + // TODO(b/315163162) Add @Deprecated keyword after 24Q2 cut. /** * Called by system whenever a device associated with this app is disconnected. * @@ -331,27 +274,13 @@ public abstract class CompanionDeviceService extends Service { } /** - * Called by the system during device events. - * - * <p>E.g. Event {@link #DEVICE_EVENT_BLE_APPEARED} will be called when the associated - * companion device comes into BLE range. - * <p>Event {@link #DEVICE_EVENT_BLE_DISAPPEARED} will be called when the associated - * companion device is no longer in BLE range. - * <p> Event {@link #DEVICE_EVENT_BT_CONNECTED} will be called when the associated - * companion device is connected. - * <p>Event {@link #DEVICE_EVENT_BT_DISCONNECTED} will be called when the associated - * companion device is disconnected. - * Note that app must receive {@link #DEVICE_EVENT_BLE_APPEARED} first before - * {@link #DEVICE_EVENT_BLE_DISAPPEARED} and {@link #DEVICE_EVENT_BT_CONNECTED} - * before {@link #DEVICE_EVENT_BT_DISCONNECTED}. + * Called by the system during device events. * - * @param associationInfo A record for the companion device. - * @param event Associated companion device's event. + * @see CompanionDeviceManager#startObservingDevicePresence(ObservingDevicePresenceRequest) */ @FlaggedApi(Flags.FLAG_DEVICE_PRESENCE) @MainThread - public void onDeviceEvent(@NonNull AssociationInfo associationInfo, - @DeviceEvent int event) { + public void onDevicePresenceEvent(@NonNull DevicePresenceEvent event) { // Do nothing. Companion apps can override this function. } @@ -390,9 +319,10 @@ public abstract class CompanionDeviceService extends Service { } @Override - public void onDeviceEvent(AssociationInfo associationInfo, int event) { - mMainHandler.postAtFrontOfQueue( - () -> mService.onDeviceEvent(associationInfo, event)); + public void onDevicePresenceEvent(DevicePresenceEvent event) { + if (Flags.devicePresence()) { + mMainHandler.postAtFrontOfQueue(() -> mService.onDevicePresenceEvent(event)); + } } } } diff --git a/core/java/android/companion/DevicePresenceEvent.aidl b/core/java/android/companion/DevicePresenceEvent.aidl new file mode 100644 index 000000000000..15215747f535 --- /dev/null +++ b/core/java/android/companion/DevicePresenceEvent.aidl @@ -0,0 +1,19 @@ + /* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + package android.companion; + + parcelable DevicePresenceEvent; diff --git a/core/java/android/companion/DevicePresenceEvent.java b/core/java/android/companion/DevicePresenceEvent.java new file mode 100644 index 000000000000..30439a5905f9 --- /dev/null +++ b/core/java/android/companion/DevicePresenceEvent.java @@ -0,0 +1,218 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.companion; + +import android.annotation.FlaggedApi; +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.os.Parcel; +import android.os.ParcelUuid; +import android.os.Parcelable; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.Objects; + +/** + * Event for observing device presence. + * + * @see CompanionDeviceManager#startObservingDevicePresence(ObservingDevicePresenceRequest) + * @see ObservingDevicePresenceRequest.Builder#setUuid(ParcelUuid) + * @see ObservingDevicePresenceRequest.Builder#setAssociationId(int) + */ +@FlaggedApi(Flags.FLAG_DEVICE_PRESENCE) +public final class DevicePresenceEvent implements Parcelable { + + /** @hide */ + @IntDef(prefix = {"EVENT"}, value = { + EVENT_BLE_APPEARED, + EVENT_BLE_DISAPPEARED, + EVENT_BT_CONNECTED, + EVENT_BT_DISCONNECTED, + EVENT_SELF_MANAGED_APPEARED, + EVENT_SELF_MANAGED_DISAPPEARED + }) + + @Retention(RetentionPolicy.SOURCE) + public @interface Event {} + + /** + * Indicate observing device presence base on the ParcelUuid but not association id. + */ + public static final int NO_ASSOCIATION = -1; + + /** + * Companion app receives + * {@link CompanionDeviceService#onDevicePresenceEvent(DevicePresenceEvent)} callback + * with this event if the device comes into BLE range. + */ + public static final int EVENT_BLE_APPEARED = 0; + + /** + * Companion app receives + * {@link CompanionDeviceService#onDevicePresenceEvent(DevicePresenceEvent)} callback + * with this event if the device is no longer in BLE range. + */ + public static final int EVENT_BLE_DISAPPEARED = 1; + + /** + * Companion app receives + * {@link CompanionDeviceService#onDevicePresenceEvent(DevicePresenceEvent)} callback + * with this event when the bluetooth device is connected. + */ + public static final int EVENT_BT_CONNECTED = 2; + + /** + * Companion app receives + * {@link CompanionDeviceService#onDevicePresenceEvent(DevicePresenceEvent)} callback + * with this event if the bluetooth device is disconnected. + */ + public static final int EVENT_BT_DISCONNECTED = 3; + + /** + * A companion app for a self-managed device will receive the callback + * {@link CompanionDeviceService#onDevicePresenceEvent(DevicePresenceEvent)} + * if it reports that a device has appeared on its + * own. + */ + public static final int EVENT_SELF_MANAGED_APPEARED = 4; + + /** + * A companion app for a self-managed device will receive the callback + * {@link CompanionDeviceService#onDevicePresenceEvent(DevicePresenceEvent)} if it reports + * that a device has disappeared on its own. + */ + public static final int EVENT_SELF_MANAGED_DISAPPEARED = 5; + private final int mAssociationId; + private final int mEvent; + @Nullable + private final ParcelUuid mUuid; + + private static final int PARCEL_UUID_NULL = 0; + + private static final int PARCEL_UUID_NOT_NULL = 1; + + /** + * Create a new DevicePresenceEvent. + */ + public DevicePresenceEvent( + int associationId, @Event int event, @Nullable ParcelUuid uuid) { + mAssociationId = associationId; + mEvent = event; + mUuid = uuid; + } + + /** + * @return The association id has been used to observe device presence. + * + * Caller will receive the valid association id if only if using + * {@link ObservingDevicePresenceRequest.Builder#setAssociationId(int)}, otherwise + * return {@link #NO_ASSOCIATION}. + * + * @see ObservingDevicePresenceRequest.Builder#setAssociationId(int) + */ + public int getAssociationId() { + return mAssociationId; + } + + /** + * @return Associated companion device's event. + */ + public int getEvent() { + return mEvent; + } + + /** + * @return The ParcelUuid has been used to observe device presence. + * + * Caller will receive the ParcelUuid if only if using + * {@link ObservingDevicePresenceRequest.Builder#setUuid(ParcelUuid)}, otherwise return null. + * + * @see ObservingDevicePresenceRequest.Builder#setUuid(ParcelUuid) + */ + + @Nullable + public ParcelUuid getUuid() { + return mUuid; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeInt(mAssociationId); + dest.writeInt(mEvent); + if (mUuid == null) { + // Write 0 to the parcel to indicate the ParcelUuid is null. + dest.writeInt(PARCEL_UUID_NULL); + } else { + dest.writeInt(PARCEL_UUID_NOT_NULL); + mUuid.writeToParcel(dest, flags); + } + } + + @Override + public boolean equals(@Nullable Object o) { + if (this == o) return true; + if (!(o instanceof DevicePresenceEvent that)) return false; + + return Objects.equals(mUuid, that.mUuid) + && mAssociationId == that.mAssociationId + && mEvent == that.mEvent; + } + + @Override + public String toString() { + return "ObservingDevicePresenceResult { " + + "Association Id= " + mAssociationId + "," + + "ParcelUuid= " + mUuid + "," + + "Event= " + mEvent + "}"; + } + + @Override + public int hashCode() { + return Objects.hash(mAssociationId, mEvent, mUuid); + } + + @NonNull + public static final Parcelable.Creator<DevicePresenceEvent> CREATOR = + new Parcelable.Creator<DevicePresenceEvent>() { + @Override + public DevicePresenceEvent[] newArray(int size) { + return new DevicePresenceEvent[size]; + } + + @Override + public DevicePresenceEvent createFromParcel(@NonNull Parcel in) { + return new DevicePresenceEvent(in); + } + }; + + private DevicePresenceEvent(@NonNull Parcel in) { + mAssociationId = in.readInt(); + mEvent = in.readInt(); + if (in.readInt() == PARCEL_UUID_NULL) { + mUuid = null; + } else { + mUuid = ParcelUuid.CREATOR.createFromParcel(in); + } + } +} diff --git a/core/java/android/companion/ICompanionDeviceManager.aidl b/core/java/android/companion/ICompanionDeviceManager.aidl index 22689f3b85c7..57d59e5e5bf0 100644 --- a/core/java/android/companion/ICompanionDeviceManager.aidl +++ b/core/java/android/companion/ICompanionDeviceManager.aidl @@ -24,8 +24,11 @@ import android.companion.IOnTransportsChangedListener; import android.companion.ISystemDataTransferCallback; import android.companion.AssociationInfo; import android.companion.AssociationRequest; +import android.companion.ObservingDevicePresenceRequest; import android.companion.datatransfer.PermissionSyncRequest; import android.content.ComponentName; +import android.os.ParcelUuid; + /** * Interface for communication with the core companion device manager service. @@ -132,4 +135,10 @@ interface ICompanionDeviceManager { byte[] getBackupPayload(int userId); void applyRestoredPayload(in byte[] payload, int userId); + + @EnforcePermission("REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE") + void startObservingDevicePresence(in ObservingDevicePresenceRequest request, in String packageName, int userId); + + @EnforcePermission("REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE") + void stopObservingDevicePresence(in ObservingDevicePresenceRequest request, in String packageName, int userId); } diff --git a/core/java/android/companion/ICompanionDeviceService.aidl b/core/java/android/companion/ICompanionDeviceService.aidl index 2a311bf1152f..f5401d2e7dbd 100644 --- a/core/java/android/companion/ICompanionDeviceService.aidl +++ b/core/java/android/companion/ICompanionDeviceService.aidl @@ -17,10 +17,12 @@ package android.companion; import android.companion.AssociationInfo; +import android.companion.DevicePresenceEvent; +import android.os.ParcelUuid; /** @hide */ oneway interface ICompanionDeviceService { void onDeviceAppeared(in AssociationInfo associationInfo); void onDeviceDisappeared(in AssociationInfo associationInfo); - void onDeviceEvent(in AssociationInfo associationInfo, int state); + void onDevicePresenceEvent(in DevicePresenceEvent event); } diff --git a/core/java/android/companion/ObservingDevicePresenceRequest.aidl b/core/java/android/companion/ObservingDevicePresenceRequest.aidl new file mode 100644 index 000000000000..fed060759711 --- /dev/null +++ b/core/java/android/companion/ObservingDevicePresenceRequest.aidl @@ -0,0 +1,19 @@ + /* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + package android.companion; + + parcelable ObservingDevicePresenceRequest;
\ No newline at end of file diff --git a/core/java/android/companion/ObservingDevicePresenceRequest.java b/core/java/android/companion/ObservingDevicePresenceRequest.java new file mode 100644 index 000000000000..f1d594e80bda --- /dev/null +++ b/core/java/android/companion/ObservingDevicePresenceRequest.java @@ -0,0 +1,208 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.companion; + +import android.annotation.FlaggedApi; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.RequiresPermission; +import android.os.Parcel; +import android.os.ParcelUuid; +import android.os.Parcelable; +import android.provider.OneTimeUseBuilder; + +import java.util.Objects; + +/** + * A request for setting the types of device for observing device presence. + * + * <p>Only supports association id or ParcelUuid and calling app must declare uses-permission + * {@link android.Manifest.permission#REQUEST_OBSERVE_DEVICE_UUID_PRESENCE} if using + * {@link Builder#setUuid(ParcelUuid)}.</p> + * + * Calling apps must use either ObservingDevicePresenceRequest.Builder#setUuid(ParcelUuid) or + * ObservingDevicePresenceRequest.Builder#setAssociationId(int), but not both. + * + * @see Builder#setUuid(ParcelUuid) + * @see Builder#setAssociationId(int) + * @see CompanionDeviceManager#startObservingDevicePresence(ObservingDevicePresenceRequest) + */ +@FlaggedApi(Flags.FLAG_DEVICE_PRESENCE) +public final class ObservingDevicePresenceRequest implements Parcelable { + private final int mAssociationId; + @Nullable private final ParcelUuid mUuid; + + private static final int PARCEL_UUID_NULL = 0; + + private static final int PARCEL_UUID_NOT_NULL = 1; + + private ObservingDevicePresenceRequest(int associationId, ParcelUuid uuid) { + mAssociationId = associationId; + mUuid = uuid; + } + + private ObservingDevicePresenceRequest(@NonNull Parcel in) { + mAssociationId = in.readInt(); + if (in.readInt() == PARCEL_UUID_NULL) { + mUuid = null; + } else { + mUuid = ParcelUuid.CREATOR.createFromParcel(in); + } + } + + /** + * @return the association id for observing device presence. It will return + * {@link DevicePresenceEvent#NO_ASSOCIATION} if using + * {@link Builder#setUuid(ParcelUuid)}. + */ + public int getAssociationId() { + return mAssociationId; + } + + /** + * @return the ParcelUuid for observing device presence. + */ + @Nullable + public ParcelUuid getUuid() { + return mUuid; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeInt(mAssociationId); + if (mUuid == null) { + // Write 0 to the parcel to indicate the ParcelUuid is null. + dest.writeInt(PARCEL_UUID_NULL); + } else { + dest.writeInt(PARCEL_UUID_NOT_NULL); + mUuid.writeToParcel(dest, flags); + } + + } + + @Override + public int describeContents() { + return 0; + } + + @NonNull + public static final Parcelable.Creator<ObservingDevicePresenceRequest> CREATOR = + new Parcelable.Creator<ObservingDevicePresenceRequest>() { + @Override + public ObservingDevicePresenceRequest[] newArray(int size) { + return new ObservingDevicePresenceRequest[size]; + } + + @Override + public ObservingDevicePresenceRequest createFromParcel(@NonNull Parcel in) { + return new ObservingDevicePresenceRequest(in); + } + }; + + @Override + public String toString() { + return "ObservingDevicePresenceRequest { " + + "Association Id= " + mAssociationId + "," + + "ParcelUuid= " + mUuid + "}"; + } + + @Override + public boolean equals(@Nullable Object o) { + if (this == o) return true; + if (!(o instanceof ObservingDevicePresenceRequest that)) return false; + + return Objects.equals(mUuid, that.mUuid) && mAssociationId == that.mAssociationId; + } + + @Override + public int hashCode() { + return Objects.hash(mAssociationId, mUuid); + } + + /** + * A builder for {@link ObservingDevicePresenceRequest} + */ + public static final class Builder extends OneTimeUseBuilder<ObservingDevicePresenceRequest> { + // Initial the association id to {@link DevicePresenceEvent.NO_ASSOCIATION} + // to indicate the value is not set yet. + private int mAssociationId = DevicePresenceEvent.NO_ASSOCIATION; + private ParcelUuid mUuid; + + public Builder() {} + + /** + * Set the association id to be observed for device presence. + * + * <p>The provided device must be {@link CompanionDeviceManager#associate associated} + * with the calling app before calling this method if using this API. + * + * Caller must implement a single {@link CompanionDeviceService} which will be bound to and + * receive callbacks to + * {@link CompanionDeviceService#onDevicePresenceEvent(DevicePresenceEvent)}.</p> + * + * <p>Calling apps must use either {@link #setUuid(ParcelUuid)} + * or this API, but not both.</p> + * + * @param associationId The association id for observing device presence. + */ + @NonNull + public Builder setAssociationId(int associationId) { + checkNotUsed(); + this.mAssociationId = associationId; + return this; + } + + /** + * Set the ParcelUuid to be observed for device presence. + * + * <p>It does not require to create the association before calling this API. + * This only supports classic Bluetooth scan and caller must implement + * a single {@link CompanionDeviceService} which will be bound to and receive callbacks to + * {@link CompanionDeviceService#onDevicePresenceEvent(DevicePresenceEvent)}.</p> + * + * <p>The Uuid should be matching one of the ParcelUuid form + * {@link android.bluetooth.BluetoothDevice#getUuids()}</p> + * + * <p>Calling apps must use either this API or {@link #setAssociationId(int)}, + * but not both.</p> + * + * @param uuid The ParcelUuid for observing device presence. + */ + @NonNull + @RequiresPermission(android.Manifest.permission.REQUEST_OBSERVE_DEVICE_UUID_PRESENCE) + public Builder setUuid(@NonNull ParcelUuid uuid) { + checkNotUsed(); + this.mUuid = uuid; + return this; + } + + @NonNull + @Override + public ObservingDevicePresenceRequest build() { + markUsed(); + if (mUuid != null && mAssociationId != DevicePresenceEvent.NO_ASSOCIATION) { + throw new IllegalStateException("Cannot observe device presence based on " + + "both ParcelUuid and association ID. Choose one or the other."); + } else if (mUuid == null && mAssociationId <= 0) { + throw new IllegalStateException("Must provide either a ParcelUuid or " + + "a valid association ID to observe device presence."); + } + + return new ObservingDevicePresenceRequest(mAssociationId, mUuid); + } + } +} diff --git a/core/java/android/companion/flags.aconfig b/core/java/android/companion/flags.aconfig index 9e410b86b6bd..d634b64b1a4e 100644 --- a/core/java/android/companion/flags.aconfig +++ b/core/java/android/companion/flags.aconfig @@ -33,4 +33,4 @@ flag { namespace: "companion" description: "Expose perm sync user consent API" bug: "309528663" -}
\ No newline at end of file +} diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java index c7a75ed5ea9c..e9b94c9f5791 100644 --- a/core/java/android/content/ContentProvider.java +++ b/core/java/android/content/ContentProvider.java @@ -41,6 +41,7 @@ import android.content.res.Configuration; import android.database.Cursor; import android.database.MatrixCursor; import android.database.SQLException; +import android.multiuser.Flags; import android.net.Uri; import android.os.AsyncTask; import android.os.Binder; @@ -146,6 +147,7 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall private boolean mExported; private boolean mNoPerms; private boolean mSingleUser; + private boolean mSystemUserOnly; private SparseBooleanArray mUsersRedirectedToOwnerForMedia = new SparseBooleanArray(); private ThreadLocal<AttributionSource> mCallingAttributionSource; @@ -377,7 +379,9 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall != PermissionChecker.PERMISSION_GRANTED && getContext().checkUriPermission(userUri, Binder.getCallingPid(), callingUid, Intent.FLAG_GRANT_READ_URI_PERMISSION) - != PackageManager.PERMISSION_GRANTED) { + != PackageManager.PERMISSION_GRANTED + && !deniedAccessSystemUserOnlyProvider(callingUserId, + mSystemUserOnly)) { FrameworkStatsLog.write(GET_TYPE_ACCESSED_WITHOUT_PERMISSION, enumCheckUriPermission, callingUid, uri.getAuthority(), type); @@ -865,6 +869,10 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall boolean checkUser(int pid, int uid, Context context) { final int callingUserId = UserHandle.getUserId(uid); + if (deniedAccessSystemUserOnlyProvider(callingUserId, mSystemUserOnly)) { + return false; + } + if (callingUserId == context.getUserId() || mSingleUser) { return true; } @@ -987,6 +995,9 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall // last chance, check against any uri grants final int callingUserId = UserHandle.getUserId(uid); + if (deniedAccessSystemUserOnlyProvider(callingUserId, mSystemUserOnly)) { + return PermissionChecker.PERMISSION_HARD_DENIED; + } final Uri userUri = (mSingleUser && !UserHandle.isSameUser(mMyUid, uid)) ? maybeAddUserId(uri, callingUserId) : uri; if (context.checkUriPermission(userUri, pid, uid, Intent.FLAG_GRANT_READ_URI_PERMISSION) @@ -2623,6 +2634,7 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall setPathPermissions(info.pathPermissions); mExported = info.exported; mSingleUser = (info.flags & ProviderInfo.FLAG_SINGLE_USER) != 0; + mSystemUserOnly = (info.flags & ProviderInfo.FLAG_SYSTEM_USER_ONLY) != 0; setAuthorities(info.authority); } if (Build.IS_DEBUGGABLE) { @@ -2756,6 +2768,11 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall String auth = uri.getAuthority(); if (!mSingleUser) { int userId = getUserIdFromAuthority(auth, UserHandle.USER_CURRENT); + if (deniedAccessSystemUserOnlyProvider(mContext.getUserId(), + mSystemUserOnly)) { + throw new SecurityException("Trying to query a SYSTEM user only content" + + " provider from user:" + mContext.getUserId()); + } if (userId != UserHandle.USER_CURRENT && userId != mContext.getUserId() // Since userId specified in content uri, the provider userId would be @@ -2929,4 +2946,16 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall Trace.traceBegin(traceTag, methodName + subInfo); } } + /** + * Return true if access to content provider is denied because it's a SYSTEM user only + * provider and the calling user is not the SYSTEM user. + * + * @param callingUserId UserId of the caller accessing the content provider. + * @param systemUserOnly true when the content provider is only available for the SYSTEM user. + */ + private static boolean deniedAccessSystemUserOnlyProvider(int callingUserId, + boolean systemUserOnly) { + return Flags.enableSystemUserOnlyForServicesAndProviders() + && (callingUserId != UserHandle.USER_SYSTEM && systemUserOnly); + } } diff --git a/core/java/android/content/pm/ArchivedActivityInfo.java b/core/java/android/content/pm/ArchivedActivityInfo.java index 1faa4373d88f..166d26503625 100644 --- a/core/java/android/content/pm/ArchivedActivityInfo.java +++ b/core/java/android/content/pm/ArchivedActivityInfo.java @@ -91,26 +91,31 @@ public final class ArchivedActivityInfo { * @hide */ public static Bitmap drawableToBitmap(Drawable drawable, int iconSize) { - if (drawable instanceof BitmapDrawable) { - return ((BitmapDrawable) drawable).getBitmap(); - - } - Bitmap bitmap; - if (drawable.getIntrinsicWidth() <= 0 || drawable.getIntrinsicHeight() <= 0) { - // Needed for drawables that are just a single color. - bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); + if (drawable instanceof BitmapDrawable) { + bitmap = ((BitmapDrawable) drawable).getBitmap(); } else { - bitmap = + if (drawable.getIntrinsicWidth() <= 0 || drawable.getIntrinsicHeight() <= 0) { + // Needed for drawables that are just a single color. + bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); + } else { + bitmap = Bitmap.createBitmap( - drawable.getIntrinsicWidth(), - drawable.getIntrinsicHeight(), - Bitmap.Config.ARGB_8888); + drawable.getIntrinsicWidth(), + drawable.getIntrinsicHeight(), + Bitmap.Config.ARGB_8888); + } + + Canvas canvas = new Canvas(bitmap); + drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); + drawable.draw(canvas); } - Canvas canvas = new Canvas(bitmap); - drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); - drawable.draw(canvas); - if (iconSize > 0 && bitmap.getWidth() > iconSize * 2 || bitmap.getHeight() > iconSize * 2) { + if (iconSize <= 0) { + return bitmap; + } + + if (bitmap.getWidth() < iconSize || bitmap.getHeight() < iconSize + || bitmap.getWidth() > iconSize * 2 || bitmap.getHeight() > iconSize * 2) { var scaledBitmap = Bitmap.createScaledBitmap(bitmap, iconSize, iconSize, true); if (scaledBitmap != bitmap) { bitmap.recycle(); @@ -235,7 +240,7 @@ public final class ArchivedActivityInfo { } @DataClass.Generated( - time = 1698789991876L, + time = 1705615445673L, codegenVersion = "1.0.23", sourceFile = "frameworks/base/core/java/android/content/pm/ArchivedActivityInfo.java", inputSignatures = "private @android.annotation.NonNull java.lang.CharSequence mLabel\nprivate @android.annotation.NonNull android.content.ComponentName mComponentName\nprivate @android.annotation.Nullable android.graphics.drawable.Drawable mIcon\nprivate @android.annotation.Nullable android.graphics.drawable.Drawable mMonochromeIcon\n @android.annotation.NonNull android.content.pm.ArchivedActivityParcel getParcel()\npublic static android.graphics.Bitmap drawableToBitmap(android.graphics.drawable.Drawable)\npublic static android.graphics.Bitmap drawableToBitmap(android.graphics.drawable.Drawable,int)\npublic static byte[] bytesFromBitmap(android.graphics.Bitmap)\nprivate static android.graphics.drawable.Drawable drawableFromCompressedBitmap(byte[])\nclass ArchivedActivityInfo extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genBuilder=false, genConstructor=false, genSetters=true)") diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java index f0efed97d8ed..c4bf18d70242 100644 --- a/core/java/android/content/pm/PackageInstaller.java +++ b/core/java/android/content/pm/PackageInstaller.java @@ -738,7 +738,7 @@ public class PackageInstaller { /** * The set of error types that can be set for - * {@link #reportUnarchivalStatus(int, int, PendingIntent)}. + * {@link #reportUnarchivalState}. * * @hide */ @@ -2421,6 +2421,7 @@ public class PackageInstaller { * facilitate the unarchival flow (e.g. user needs to log in). * @throws PackageManager.NameNotFoundException if no unarchival with {@code unarchiveId} exists */ + // TODO(b/314960798) Remove old API once it's unused @RequiresPermission(anyOf = { Manifest.permission.INSTALL_PACKAGES, Manifest.permission.REQUEST_INSTALL_PACKAGES}) @@ -2438,6 +2439,30 @@ public class PackageInstaller { } } + /** + * Reports the state of an unarchival to the system. + * + * @see UnarchivalState for the different state options. + * @throws PackageManager.NameNotFoundException if no unarchival with {@code unarchiveId} exists + */ + @RequiresPermission(anyOf = { + Manifest.permission.INSTALL_PACKAGES, + Manifest.permission.REQUEST_INSTALL_PACKAGES}) + @FlaggedApi(Flags.FLAG_ARCHIVING) + public void reportUnarchivalState(@NonNull UnarchivalState unarchivalState) + throws PackageManager.NameNotFoundException { + Objects.requireNonNull(unarchivalState); + try { + mInstaller.reportUnarchivalStatus(unarchivalState.getUnarchiveId(), + unarchivalState.getStatus(), unarchivalState.getRequiredStorageBytes(), + unarchivalState.getUserActionIntent(), new UserHandle(mUserId)); + } catch (ParcelableException e) { + e.maybeRethrow(PackageManager.NameNotFoundException.class); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + // (b/239722738) This class serves as a bridge between the PackageLite class, which // is a hidden class, and the consumers of this class. (e.g. InstallInstalling.java) // This is a part of an effort to remove dependency on hidden APIs and use SystemAPIs or @@ -2693,6 +2718,8 @@ public class PackageInstaller { /** @hide */ public long rollbackLifetimeMillis = 0; /** {@hide} */ + public int rollbackImpactLevel = PackageManager.ROLLBACK_USER_IMPACT_LOW; + /** {@hide} */ public boolean forceQueryableOverride; /** {@hide} */ public int requireUserAction = USER_ACTION_UNSPECIFIED; @@ -2749,6 +2776,7 @@ public class PackageInstaller { } rollbackDataPolicy = source.readInt(); rollbackLifetimeMillis = source.readLong(); + rollbackImpactLevel = source.readInt(); requireUserAction = source.readInt(); packageSource = source.readInt(); applicationEnabledSettingPersistent = source.readBoolean(); @@ -2783,6 +2811,7 @@ public class PackageInstaller { ret.dataLoaderParams = dataLoaderParams; ret.rollbackDataPolicy = rollbackDataPolicy; ret.rollbackLifetimeMillis = rollbackLifetimeMillis; + ret.rollbackImpactLevel = rollbackImpactLevel; ret.requireUserAction = requireUserAction; ret.packageSource = packageSource; ret.applicationEnabledSettingPersistent = applicationEnabledSettingPersistent; @@ -3121,6 +3150,28 @@ public class PackageInstaller { } /** + * rollbackImpactLevel is a measure of impact a rollback has on the user. This can take one + * of 3 values: + * <ul> + * <li>{@link PackageManager#ROLLBACK_USER_IMPACT_LOW} (default)</li> + * <li>{@link PackageManager#ROLLBACK_USER_IMPACT_HIGH} (1)</li> + * <li>{@link PackageManager#ROLLBACK_USER_IMPACT_ONLY_MANUAL} (2)</li> + * </ul> + * + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.MANAGE_ROLLBACKS) + @FlaggedApi(Flags.FLAG_RECOVERABILITY_DETECTION) + public void setRollbackImpactLevel(@PackageManager.RollbackImpactLevel int impactLevel) { + if ((installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) == 0) { + throw new IllegalArgumentException( + "Can't set rollbackImpactLevel when rollback is not enabled"); + } + rollbackImpactLevel = impactLevel; + } + + /** * @deprecated use {@link #setRequestDowngrade(boolean)}. * {@hide} */ @@ -3493,6 +3544,7 @@ public class PackageInstaller { pw.printPair("dataLoaderParams", dataLoaderParams); pw.printPair("rollbackDataPolicy", rollbackDataPolicy); pw.printPair("rollbackLifetimeMillis", rollbackLifetimeMillis); + pw.printPair("rollbackImpactLevel", rollbackImpactLevel); pw.printPair("applicationEnabledSettingPersistent", applicationEnabledSettingPersistent); pw.printHexPair("developmentInstallFlags", developmentInstallFlags); @@ -3536,6 +3588,7 @@ public class PackageInstaller { } dest.writeInt(rollbackDataPolicy); dest.writeLong(rollbackLifetimeMillis); + dest.writeInt(rollbackImpactLevel); dest.writeInt(requireUserAction); dest.writeInt(packageSource); dest.writeBoolean(applicationEnabledSettingPersistent); @@ -3734,6 +3787,9 @@ public class PackageInstaller { public long rollbackLifetimeMillis; /** {@hide} */ + public int rollbackImpactLevel; + + /** {@hide} */ public int requireUserAction; /** {@hide} */ @@ -3801,6 +3857,7 @@ public class PackageInstaller { isPreapprovalRequested = source.readBoolean(); rollbackDataPolicy = source.readInt(); rollbackLifetimeMillis = source.readLong(); + rollbackImpactLevel = source.readInt(); createdMillis = source.readLong(); requireUserAction = source.readInt(); installerUid = source.readInt(); @@ -4438,6 +4495,7 @@ public class PackageInstaller { dest.writeBoolean(isPreapprovalRequested); dest.writeInt(rollbackDataPolicy); dest.writeLong(rollbackLifetimeMillis); + dest.writeInt(rollbackImpactLevel); dest.writeLong(createdMillis); dest.writeInt(requireUserAction); dest.writeInt(installerUid); @@ -4708,10 +4766,10 @@ public class PackageInstaller { codegenVersion = "1.0.23", sourceFile = "frameworks/base/core/java/android/content/pm/PackageInstaller.java", inputSignatures = "private final @android.annotation.Nullable android.graphics.Bitmap mIcon\nprivate final @android.annotation.NonNull java.lang.CharSequence mLabel\nprivate final @android.annotation.NonNull android.icu.util.ULocale mLocale\nprivate final @android.annotation.NonNull java.lang.String mPackageName\npublic static final @android.annotation.NonNull android.os.Parcelable.Creator<android.content.pm.PackageInstaller.PreapprovalDetails> CREATOR\npublic @java.lang.Override void writeToParcel(android.os.Parcel,int)\npublic @java.lang.Override int describeContents()\nclass PreapprovalDetails extends java.lang.Object implements [android.os.Parcelable]\nprivate @android.annotation.Nullable android.graphics.Bitmap mIcon\nprivate @android.annotation.NonNull java.lang.CharSequence mLabel\nprivate @android.annotation.NonNull android.icu.util.ULocale mLocale\nprivate @android.annotation.NonNull java.lang.String mPackageName\nprivate long mBuilderFieldsSet\npublic @android.annotation.NonNull android.content.pm.PackageInstaller.PreapprovalDetails.Builder setIcon(android.graphics.Bitmap)\npublic @android.annotation.NonNull android.content.pm.PackageInstaller.PreapprovalDetails.Builder setLabel(java.lang.CharSequence)\npublic @android.annotation.NonNull android.content.pm.PackageInstaller.PreapprovalDetails.Builder setLocale(android.icu.util.ULocale)\npublic @android.annotation.NonNull android.content.pm.PackageInstaller.PreapprovalDetails.Builder setPackageName(java.lang.String)\npublic @android.annotation.NonNull android.content.pm.PackageInstaller.PreapprovalDetails build()\nprivate void checkNotUsed()\nclass Builder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false, genToString=true)") + @Deprecated private void __metadata() {} - //@formatter:on // End of generated code @@ -5102,13 +5160,188 @@ public class PackageInstaller { codegenVersion = "1.0.23", sourceFile = "frameworks/base/core/java/android/content/pm/PackageInstaller.java", inputSignatures = "public static final @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints GENTLE_UPDATE\nprivate final boolean mDeviceIdleRequired\nprivate final boolean mAppNotForegroundRequired\nprivate final boolean mAppNotInteractingRequired\nprivate final boolean mAppNotTopVisibleRequired\nprivate final boolean mNotInCallRequired\nclass InstallConstraints extends java.lang.Object implements [android.os.Parcelable]\nprivate boolean mDeviceIdleRequired\nprivate boolean mAppNotForegroundRequired\nprivate boolean mAppNotInteractingRequired\nprivate boolean mAppNotTopVisibleRequired\nprivate boolean mNotInCallRequired\npublic @android.annotation.SuppressLint @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints.Builder setDeviceIdleRequired()\npublic @android.annotation.SuppressLint @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints.Builder setAppNotForegroundRequired()\npublic @android.annotation.SuppressLint @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints.Builder setAppNotInteractingRequired()\npublic @android.annotation.SuppressLint @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints.Builder setAppNotTopVisibleRequired()\npublic @android.annotation.SuppressLint @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints.Builder setNotInCallRequired()\npublic @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints build()\nclass Builder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genParcelable=true, genHiddenConstructor=true, genEqualsHashCode=true)") + @Deprecated private void __metadata() {} - //@formatter:on // End of generated code } + /** + * Used to communicate the unarchival state in {@link #reportUnarchivalState}. + */ + @FlaggedApi(Flags.FLAG_ARCHIVING) + public static final class UnarchivalState { + + /** + * The caller is able to facilitate the unarchival for the given {@code unarchiveId}. + * + * @param unarchiveId the ID provided by the system as part of the intent.action.UNARCHIVE + * broadcast with EXTRA_UNARCHIVE_ID. + */ + @NonNull + public static UnarchivalState createOkState(int unarchiveId) { + return new UnarchivalState(unarchiveId, UNARCHIVAL_OK, /* requiredStorageBytes= */ -1, + /* userActionIntent= */ null); + } + + /** + * User action is required before commencing with the unarchival for the given + * {@code unarchiveId}. E.g., this could be used if it's necessary for the user to sign-in + * first. + * + * @param unarchiveId the ID provided by the system as part of the + * intent.action.UNARCHIVE + * broadcast with EXTRA_UNARCHIVE_ID. + * @param userActionIntent optional intent to start a follow up action required to + * facilitate the unarchival flow (e.g. user needs to log in). + */ + @NonNull + public static UnarchivalState createUserActionRequiredState(int unarchiveId, + @NonNull PendingIntent userActionIntent) { + Objects.requireNonNull(userActionIntent); + return new UnarchivalState(unarchiveId, UNARCHIVAL_ERROR_USER_ACTION_NEEDED, + /* requiredStorageBytes= */ -1, userActionIntent); + } + + /** + * There is not enough storage to start the unarchival for the given {@code unarchiveId}. + * + * @param unarchiveId the ID provided by the system as part of the + * intent.action.UNARCHIVE + * broadcast with EXTRA_UNARCHIVE_ID. + * @param requiredStorageBytes ff the error is UNARCHIVAL_ERROR_INSUFFICIENT_STORAGE this + * field should be set to specify how many additional bytes of + * storage are required to unarchive the app. + * @param userActionIntent can optionally be set to provide a custom storage-clearing + * action. + */ + @NonNull + public static UnarchivalState createInsufficientStorageState(int unarchiveId, + long requiredStorageBytes, @Nullable PendingIntent userActionIntent) { + return new UnarchivalState(unarchiveId, UNARCHIVAL_ERROR_INSUFFICIENT_STORAGE, + requiredStorageBytes, userActionIntent); + } + + /** + * The device has no data connectivity and unarchival cannot be started for the given + * {@code unarchiveId}. + * + * @param unarchiveId the ID provided by the system as part of the intent.action.UNARCHIVE + * broadcast with EXTRA_UNARCHIVE_ID. + */ + @NonNull + public static UnarchivalState createNoConnectivityState(int unarchiveId) { + return new UnarchivalState(unarchiveId, UNARCHIVAL_ERROR_NO_CONNECTIVITY, + /* requiredStorageBytes= */ -1,/* userActionIntent= */ null); + } + + /** + * Generic error state for all cases that are not covered by other methods in this class. + * + * @param unarchiveId the ID provided by the system as part of the intent.action.UNARCHIVE + * broadcast with EXTRA_UNARCHIVE_ID. + */ + @NonNull + public static UnarchivalState createGenericErrorState(int unarchiveId) { + return new UnarchivalState(unarchiveId, UNARCHIVAL_GENERIC_ERROR, + /* requiredStorageBytes= */ -1,/* userActionIntent= */ null); + } + + + /** + * The ID provided by the system as part of the intent.action.UNARCHIVE broadcast with + * EXTRA_UNARCHIVE_ID. + */ + private final int mUnarchiveId; + + /** Used for the system to provide the user with necessary follow-up steps or errors. */ + @UnarchivalStatus + private final int mStatus; + + /** + * If the error is UNARCHIVAL_ERROR_INSUFFICIENT_STORAGE this field should be set to specify + * how many additional bytes of storage are required to unarchive the app. + */ + private final long mRequiredStorageBytes; + + /** + * Optional intent to start a follow up action required to facilitate the unarchival flow + * (e.g., user needs to log in). + */ + @Nullable + private final PendingIntent mUserActionIntent; + + /** + * Creates a new UnarchivalState. + * + * @param unarchiveId The ID provided by the system as part of the + * intent.action.UNARCHIVE broadcast with + * EXTRA_UNARCHIVE_ID. + * @param status Used for the system to provide the user with necessary + * follow-up steps or errors. + * @param requiredStorageBytes If the error is UNARCHIVAL_ERROR_INSUFFICIENT_STORAGE this + * field should be set to specify + * how many additional bytes of storage are required to + * unarchive the app. + * @param userActionIntent Optional intent to start a follow up action required to + * facilitate the unarchival flow + * (e.g,. user needs to log in). + * @hide + */ + private UnarchivalState( + int unarchiveId, + @UnarchivalStatus int status, + long requiredStorageBytes, + @Nullable PendingIntent userActionIntent) { + this.mUnarchiveId = unarchiveId; + this.mStatus = status; + com.android.internal.util.AnnotationValidations.validate( + UnarchivalStatus.class, null, mStatus); + this.mRequiredStorageBytes = requiredStorageBytes; + this.mUserActionIntent = userActionIntent; + } + + /** + * The ID provided by the system as part of the intent.action.UNARCHIVE broadcast with + * EXTRA_UNARCHIVE_ID. + * + * @hide + */ + int getUnarchiveId() { + return mUnarchiveId; + } + + /** + * Used for the system to provide the user with necessary follow-up steps or errors. + * + * @hide + */ + @UnarchivalStatus int getStatus() { + return mStatus; + } + + /** + * If the error is UNARCHIVAL_ERROR_INSUFFICIENT_STORAGE this field should be set to specify + * how many additional bytes of storage are required to unarchive the app. + * + * @hide + */ + long getRequiredStorageBytes() { + return mRequiredStorageBytes; + } + + /** + * Optional intent to start a follow up action required to facilitate the unarchival flow + * (e.g. user needs to log in). + * + * @hide + */ + @Nullable PendingIntent getUserActionIntent() { + return mUserActionIntent; + } + } + } diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index aabbe698703c..4724e866f094 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -1501,6 +1501,44 @@ public abstract class PackageManager { public static final int ROLLBACK_DATA_POLICY_RETAIN = 2; /** @hide */ + @IntDef(prefix = {"ROLLBACK_USER_IMPACT_"}, value = { + ROLLBACK_USER_IMPACT_LOW, + ROLLBACK_USER_IMPACT_HIGH, + ROLLBACK_USER_IMPACT_ONLY_MANUAL, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface RollbackImpactLevel {} + + /** + * Rollback will be performed automatically in response to native crashes on startup or + * persistent service crashes. More suitable for apps that do not store any user data. + * + * @hide + */ + @SystemApi + @FlaggedApi(android.content.pm.Flags.FLAG_RECOVERABILITY_DETECTION) + public static final int ROLLBACK_USER_IMPACT_LOW = 0; + + /** + * Rollback will be performed automatically only when the device is found to be unrecoverable. + * More suitable for apps that store user data and have higher impact on user. + * + * @hide + */ + @SystemApi + @FlaggedApi(android.content.pm.Flags.FLAG_RECOVERABILITY_DETECTION) + public static final int ROLLBACK_USER_IMPACT_HIGH = 1; + + /** + * Rollback will not be performed automatically. It can be triggered externally. + * + * @hide + */ + @SystemApi + @FlaggedApi(android.content.pm.Flags.FLAG_RECOVERABILITY_DETECTION) + public static final int ROLLBACK_USER_IMPACT_ONLY_MANUAL = 2; + + /** @hide */ @IntDef(flag = true, prefix = { "INSTALL_" }, value = { INSTALL_REPLACE_EXISTING, INSTALL_ALLOW_TEST, diff --git a/core/java/android/content/pm/ProviderInfo.java b/core/java/android/content/pm/ProviderInfo.java index 9e553dbfb719..de33fa8b2328 100644 --- a/core/java/android/content/pm/ProviderInfo.java +++ b/core/java/android/content/pm/ProviderInfo.java @@ -89,6 +89,15 @@ public final class ProviderInfo extends ComponentInfo public static final int FLAG_VISIBLE_TO_INSTANT_APP = 0x100000; /** + * Bit in {@link #flags}: If set, this provider will only be available + * for the system user. + * Set from the android.R.attr#systemUserOnly attribute. + * In Sync with {@link ActivityInfo#FLAG_SYSTEM_USER_ONLY} + * @hide + */ + public static final int FLAG_SYSTEM_USER_ONLY = ActivityInfo.FLAG_SYSTEM_USER_ONLY; + + /** * Bit in {@link #flags}: If set, a single instance of the provider will * run for all users on the device. Set from the * {@link android.R.attr#singleUser} attribute. diff --git a/core/java/android/content/pm/ServiceInfo.java b/core/java/android/content/pm/ServiceInfo.java index ae46c027505e..2b378b1f09d0 100644 --- a/core/java/android/content/pm/ServiceInfo.java +++ b/core/java/android/content/pm/ServiceInfo.java @@ -101,6 +101,14 @@ public class ServiceInfo extends ComponentInfo public static final int FLAG_VISIBLE_TO_INSTANT_APP = 0x100000; /** + * @hide Bit in {@link #flags}: If set, this service will only be available + * for the system user. + * Set from the android.R.attr#systemUserOnly attribute. + * In Sync with {@link ActivityInfo#FLAG_SYSTEM_USER_ONLY} + */ + public static final int FLAG_SYSTEM_USER_ONLY = ActivityInfo.FLAG_SYSTEM_USER_ONLY; + + /** * Bit in {@link #flags}: If set, a single instance of the service will * run for all users on the device. Set from the * {@link android.R.attr#singleUser} attribute. diff --git a/core/java/android/content/pm/flags.aconfig b/core/java/android/content/pm/flags.aconfig index a2cd3e153b3e..e4e9fbaf2c55 100644 --- a/core/java/android/content/pm/flags.aconfig +++ b/core/java/android/content/pm/flags.aconfig @@ -146,3 +146,10 @@ flag { bug: "281848623" } +flag { + name: "recoverability_detection" + namespace: "package_manager_service" + description: "Feature flag to enable recoverability detection feature. It includes GMS core rollback and improvements to rescue party." + bug: "291135724" + is_fixed_read_only: true +} diff --git a/core/java/android/content/pm/multiuser.aconfig b/core/java/android/content/pm/multiuser.aconfig index 7c5d3054c945..9644d8095a4d 100644 --- a/core/java/android/content/pm/multiuser.aconfig +++ b/core/java/android/content/pm/multiuser.aconfig @@ -77,4 +77,18 @@ flag { namespace: "profile_experiences" description: "Move the quiet mode operations, happening on a background thread today, to a separate thread." bug: "320483504" -}
\ No newline at end of file +} + +flag { + name: "enable_private_space_autolock_on_restarts" + namespace: "profile_experiences" + description: "Enable auto-locking private space on device restarts" + bug: "296993385" +} +flag { + name: "enable_system_user_only_for_services_and_providers" + namespace: "multiuser" + description: "Enable systemUserOnly manifest attribute for services and providers." + bug: "302354856" + is_fixed_read_only: true +} diff --git a/core/java/android/content/pm/overlay/OverlayPaths.java b/core/java/android/content/pm/overlay/OverlayPaths.java index a4db733af013..bd74b0b9293c 100644 --- a/core/java/android/content/pm/overlay/OverlayPaths.java +++ b/core/java/android/content/pm/overlay/OverlayPaths.java @@ -49,6 +49,13 @@ public class OverlayPaths { public static class Builder { final OverlayPaths mPaths = new OverlayPaths(); + public Builder() {} + + public Builder(@NonNull OverlayPaths base) { + mPaths.mResourceDirs.addAll(base.getResourceDirs()); + mPaths.mOverlayPaths.addAll(base.getOverlayPaths()); + } + /** * Adds a non-APK path to the contents of {@link OverlayPaths#getOverlayPaths()}. */ diff --git a/core/java/android/content/rollback/RollbackInfo.java b/core/java/android/content/rollback/RollbackInfo.java index a363718a8b1d..d128055fec6d 100644 --- a/core/java/android/content/rollback/RollbackInfo.java +++ b/core/java/android/content/rollback/RollbackInfo.java @@ -16,8 +16,12 @@ package android.content.rollback; +import android.annotation.FlaggedApi; import android.annotation.NonNull; import android.annotation.SystemApi; +import android.annotation.TestApi; +import android.content.pm.Flags; +import android.content.pm.PackageManager; import android.content.pm.VersionedPackage; import android.os.Parcel; import android.os.Parcelable; @@ -25,17 +29,14 @@ import android.os.Parcelable; import java.util.List; /** - * Information about a set of packages that can be, or already have been - * rolled back together. + * Information about a set of packages that can be, or already have been rolled back together. * * @hide */ @SystemApi public final class RollbackInfo implements Parcelable { - /** - * A unique identifier for the rollback. - */ + /** A unique identifier for the rollback. */ private final int mRollbackId; private final List<PackageRollbackInfo> mPackages; @@ -44,15 +45,39 @@ public final class RollbackInfo implements Parcelable { private final boolean mIsStaged; private int mCommittedSessionId; + private int mRollbackImpactLevel; /** @hide */ - public RollbackInfo(int rollbackId, List<PackageRollbackInfo> packages, boolean isStaged, - List<VersionedPackage> causePackages, int committedSessionId) { + public RollbackInfo( + int rollbackId, + List<PackageRollbackInfo> packages, + boolean isStaged, + List<VersionedPackage> causePackages, + int committedSessionId, + @PackageManager.RollbackImpactLevel int rollbackImpactLevel) { this.mRollbackId = rollbackId; this.mPackages = packages; this.mIsStaged = isStaged; this.mCausePackages = causePackages; this.mCommittedSessionId = committedSessionId; + this.mRollbackImpactLevel = rollbackImpactLevel; + } + + /** @hide */ + public RollbackInfo( + int rollbackId, + List<PackageRollbackInfo> packages, + boolean isStaged, + List<VersionedPackage> causePackages, + int committedSessionId) { + // If impact level is not set default to 0 + this( + rollbackId, + packages, + isStaged, + causePackages, + committedSessionId, + PackageManager.ROLLBACK_USER_IMPACT_LOW); } private RollbackInfo(Parcel in) { @@ -61,34 +86,28 @@ public final class RollbackInfo implements Parcelable { mIsStaged = in.readBoolean(); mCausePackages = in.createTypedArrayList(VersionedPackage.CREATOR); mCommittedSessionId = in.readInt(); + mRollbackImpactLevel = in.readInt(); } - /** - * Returns a unique identifier for this rollback. - */ + /** Returns a unique identifier for this rollback. */ public int getRollbackId() { return mRollbackId; } - /** - * Returns the list of package that are rolled back. - */ + /** Returns the list of package that are rolled back. */ @NonNull public List<PackageRollbackInfo> getPackages() { return mPackages; } - /** - * Returns true if this rollback requires reboot to take effect after - * being committed. - */ + /** Returns true if this rollback requires reboot to take effect after being committed. */ public boolean isStaged() { return mIsStaged; } /** - * Returns the session ID for the committed rollback for staged rollbacks. - * Only applicable for rollbacks that have been committed. + * Returns the session ID for the committed rollback for staged rollbacks. Only applicable for + * rollbacks that have been committed. */ public int getCommittedSessionId() { return mCommittedSessionId; @@ -96,6 +115,7 @@ public final class RollbackInfo implements Parcelable { /** * Sets the session ID for the committed rollback for staged rollbacks. + * * @hide */ public void setCommittedSessionId(int sessionId) { @@ -103,15 +123,40 @@ public final class RollbackInfo implements Parcelable { } /** - * Gets the list of package versions that motivated this rollback. - * As provided to {@link #commitRollback} when the rollback was committed. - * This is only applicable for rollbacks that have been committed. + * Gets the list of package versions that motivated this rollback. As provided to {@link + * #commitRollback} when the rollback was committed. This is only applicable for rollbacks that + * have been committed. */ @NonNull public List<VersionedPackage> getCausePackages() { return mCausePackages; } + /** + * Get rollback impact level. Refer {@link + * android.content.pm.PackageInstaller.SessionParams#setRollbackImpactLevel(int)} for more info + * on impact level. + * + * @hide + */ + @TestApi + @FlaggedApi(Flags.FLAG_RECOVERABILITY_DETECTION) + public @PackageManager.RollbackImpactLevel int getRollbackImpactLevel() { + return mRollbackImpactLevel; + } + + /** + * Set rollback impact level. Refer {@link + * android.content.pm.PackageInstaller.SessionParams#setRollbackImpactLevel(int)} for more info + * on impact level. + * + * @hide + */ + public void setRollbackImpactLevel( + @PackageManager.RollbackImpactLevel int rollbackImpactLevel) { + mRollbackImpactLevel = rollbackImpactLevel; + } + @Override public int describeContents() { return 0; @@ -124,16 +169,17 @@ public final class RollbackInfo implements Parcelable { out.writeBoolean(mIsStaged); out.writeTypedList(mCausePackages); out.writeInt(mCommittedSessionId); + out.writeInt(mRollbackImpactLevel); } public static final @android.annotation.NonNull Parcelable.Creator<RollbackInfo> CREATOR = new Parcelable.Creator<RollbackInfo>() { - public RollbackInfo createFromParcel(Parcel in) { - return new RollbackInfo(in); - } - - public RollbackInfo[] newArray(int size) { - return new RollbackInfo[size]; - } - }; + public RollbackInfo createFromParcel(Parcel in) { + return new RollbackInfo(in); + } + + public RollbackInfo[] newArray(int size) { + return new RollbackInfo[size]; + } + }; } diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java index 8a4f678b52f2..35ae3c9e23c7 100644 --- a/core/java/android/database/sqlite/SQLiteDatabase.java +++ b/core/java/android/database/sqlite/SQLiteDatabase.java @@ -40,12 +40,15 @@ import android.os.Looper; import android.os.OperationCanceledException; import android.os.SystemProperties; import android.text.TextUtils; +import android.util.ArrayMap; import android.util.ArraySet; import android.util.EventLog; import android.util.Log; import android.util.Pair; import android.util.Printer; +import com.android.internal.annotations.GuardedBy; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.Preconditions; import dalvik.annotation.optimization.NeverCompile; @@ -103,8 +106,14 @@ public final class SQLiteDatabase extends SQLiteClosable { // Stores reference to all databases opened in the current process. // (The referent Object is not used at this time.) // INVARIANT: Guarded by sActiveDatabases. + @GuardedBy("sActiveDatabases") private static WeakHashMap<SQLiteDatabase, Object> sActiveDatabases = new WeakHashMap<>(); + // Tracks which database files are currently open. If a database file is opened more than + // once at any given moment, the associated databases are marked as "concurrent". + @GuardedBy("sActiveDatabases") + private static final OpenTracker sOpenTracker = new OpenTracker(); + // Thread-local for database sessions that belong to this database. // Each thread has its own database session. // INVARIANT: Immutable. @@ -510,6 +519,7 @@ public final class SQLiteDatabase extends SQLiteClosable { private void dispose(boolean finalized) { final SQLiteConnectionPool pool; + final String path; synchronized (mLock) { if (mCloseGuardLocked != null) { if (finalized) { @@ -520,10 +530,12 @@ public final class SQLiteDatabase extends SQLiteClosable { pool = mConnectionPoolLocked; mConnectionPoolLocked = null; + path = isInMemoryDatabase() ? null : getPath(); } if (!finalized) { synchronized (sActiveDatabases) { + sOpenTracker.close(path); sActiveDatabases.remove(this); } @@ -1132,6 +1144,74 @@ public final class SQLiteDatabase extends SQLiteClosable { } } + /** + * Track the number of times a database file has been opened. There is a primary connection + * associated with every open database, and these can contend with each other, leading to + * unexpected SQLiteDatabaseLockedException exceptions. The tracking here is only advisory: + * multiply-opened databases are logged but no other action is taken. + * + * This class is not thread-safe. + */ + private static class OpenTracker { + // The list of currently-open databases. This maps the database file to the number of + // currently-active opens. + private final ArrayMap<String, Integer> mOpens = new ArrayMap<>(); + + // The maximum number of concurrently open database paths that will be stored. Once this + // many paths have been recorded, further paths are logged but not saved. + private static final int MAX_RECORDED_PATHS = 20; + + // The list of databases that were ever concurrently opened. + private final ArraySet<String> mConcurrent = new ArraySet<>(); + + /** Return the canonical path. On error, just return the input path. */ + private static String normalize(String path) { + try { + return new File(path).toPath().toRealPath().toString(); + } catch (Exception e) { + // If there is an IO or security exception, just continue, using the input path. + return path; + } + } + + /** Return true if the path is currently open in another SQLiteDatabase instance. */ + void open(@Nullable String path) { + if (path == null) return; + path = normalize(path); + + Integer count = mOpens.get(path); + if (count == null || count == 0) { + mOpens.put(path, 1); + return; + } else { + mOpens.put(path, count + 1); + if (mConcurrent.size() < MAX_RECORDED_PATHS) { + mConcurrent.add(path); + } + Log.w(TAG, "multiple primary connections on " + path); + return; + } + } + + void close(@Nullable String path) { + if (path == null) return; + path = normalize(path); + Integer count = mOpens.get(path); + if (count == null || count <= 0) { + Log.e(TAG, "open database counting failure on " + path); + } else if (count == 1) { + // Implicitly set the count to zero, and make mOpens smaller. + mOpens.remove(path); + } else { + mOpens.put(path, count - 1); + } + } + + ArraySet<String> getConcurrentDatabasePaths() { + return new ArraySet<>(mConcurrent); + } + } + private void open() { try { try { @@ -1153,14 +1233,17 @@ public final class SQLiteDatabase extends SQLiteClosable { } private void openInner() { + final String path; synchronized (mLock) { assert mConnectionPoolLocked == null; mConnectionPoolLocked = SQLiteConnectionPool.open(mConfigurationLocked); mCloseGuardLocked.open("close"); + path = isInMemoryDatabase() ? null : getPath(); } synchronized (sActiveDatabases) { sActiveDatabases.put(this, null); + sOpenTracker.open(path); } } @@ -2345,6 +2428,17 @@ public final class SQLiteDatabase extends SQLiteClosable { } /** + * Return list of databases that have been concurrently opened. + * @hide + */ + @VisibleForTesting + public static ArraySet<String> getConcurrentDatabasePaths() { + synchronized (sActiveDatabases) { + return sOpenTracker.getConcurrentDatabasePaths(); + } + } + + /** * Returns true if the new version code is greater than the current database version. * * @param newVersion The new version code. @@ -2766,6 +2860,19 @@ public final class SQLiteDatabase extends SQLiteClosable { dumpDatabaseDirectory(printer, new File(dir), isSystem); } } + + // Dump concurrently-opened database files, if any + final ArraySet<String> concurrent; + synchronized (sActiveDatabases) { + concurrent = sOpenTracker.getConcurrentDatabasePaths(); + } + if (concurrent.size() > 0) { + printer.println(""); + printer.println("Concurrently opened database files"); + for (String f : concurrent) { + printer.println(" " + f); + } + } } private static void dumpDatabaseDirectory(Printer pw, File dir, boolean isSystem) { diff --git a/core/java/android/hardware/HardwareBuffer.java b/core/java/android/hardware/HardwareBuffer.java index f5b3a7b56302..0047b7d69282 100644 --- a/core/java/android/hardware/HardwareBuffer.java +++ b/core/java/android/hardware/HardwareBuffer.java @@ -67,8 +67,8 @@ public final class HardwareBuffer implements Parcelable, AutoCloseable { S_UI8, YCBCR_P010, R_8, - R_16_UINT, - RG_1616_UINT, + R_16, + RG_1616, RGBA_10101010, }) public @interface Format { @@ -119,13 +119,13 @@ public final class HardwareBuffer implements Parcelable, AutoCloseable { * implicit unsigned normalized. */ @FlaggedApi(com.android.graphics.hwui.flags.Flags.FLAG_REQUESTED_FORMATS_V) - public static final int R_16_UINT = 0x39; + public static final int R_16 = 0x39; /** * Format: 16 bits each red, green. Bits should be represented in unsigned integer, * instead of the implicit unsigned normalized. */ @FlaggedApi(com.android.graphics.hwui.flags.Flags.FLAG_REQUESTED_FORMATS_V) - public static final int RG_1616_UINT = 0x3a; + public static final int RG_1616 = 0x3a; /** Format: 10 bits each red, green, blue, alpha */ @FlaggedApi(com.android.graphics.hwui.flags.Flags.FLAG_REQUESTED_FORMATS_V) public static final int RGBA_10101010 = 0x3b; diff --git a/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java b/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java index 20b09326e9c0..1867a17d8756 100644 --- a/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java +++ b/core/java/android/hardware/camera2/CameraExtensionCharacteristics.java @@ -847,16 +847,18 @@ public final class CameraExtensionCharacteristics { * of the camera resolutions advertised by * {@link StreamConfigurationMap#getOutputSizes}.</p> * - * <p>Device-specific extensions currently support at most two + * <p>Device-specific extensions currently support at most three * multi-frame capture surface formats. ImageFormat.JPEG will be supported by all - * extensions and ImageFormat.YUV_420_888 may or may not be supported.</p> + * extensions while ImageFormat.YUV_420_888 and ImageFormat.JPEG_R may or may not be + * supported.</p> * * @param extension the extension type * @param format device-specific extension output format * @return non-modifiable list of available sizes or an empty list if the format is not * supported. - * @throws IllegalArgumentException in case of format different from ImageFormat.JPEG / - * ImageFormat.YUV_420_888; or unsupported extension. + * @throws IllegalArgumentException in case of format different from ImageFormat.JPEG, + * ImageFormat.YUV_420_888, ImageFormat.JPEG_R; or + * unsupported extension. */ public @NonNull List<Size> getExtensionSupportedSizes(@Extension int extension, int format) { @@ -940,14 +942,16 @@ public final class CameraExtensionCharacteristics { * @param format device-specific extension output format * @return the range of estimated minimal and maximal capture latency in milliseconds * or null if no capture latency info can be provided - * @throws IllegalArgumentException in case of format different from {@link ImageFormat#JPEG} / - * {@link ImageFormat#YUV_420_888}; or unsupported extension. + * @throws IllegalArgumentException in case of format different from {@link ImageFormat#JPEG}, + * {@link ImageFormat#YUV_420_888}, {@link ImageFormat#JPEG_R}; + * or unsupported extension. */ public @Nullable Range<Long> getEstimatedCaptureLatencyRangeMillis(@Extension int extension, @NonNull Size captureOutputSize, @ImageFormat.Format int format) { switch (format) { case ImageFormat.YUV_420_888: case ImageFormat.JPEG: + case ImageFormat.JPEG_R: //No op break; default: @@ -994,6 +998,10 @@ public final class CameraExtensionCharacteristics { // specific and cannot be estimated accurately enough. return null; } + if (format == ImageFormat.JPEG_R) { + // JpegR/UltraHDR is not supported for basic extensions + return null; + } LatencyRange latencyRange = extenders.second.getEstimatedCaptureLatencyRange(sz); if (latencyRange != null) { diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java index 3a32b2bab682..4dc32d5039b6 100644 --- a/core/java/android/os/FileUtils.java +++ b/core/java/android/os/FileUtils.java @@ -25,6 +25,7 @@ import static android.os.ParcelFileDescriptor.MODE_WRITE_ONLY; import static android.system.OsConstants.EINVAL; import static android.system.OsConstants.ENOSYS; import static android.system.OsConstants.F_OK; +import static android.system.OsConstants.EIO; import static android.system.OsConstants.O_ACCMODE; import static android.system.OsConstants.O_APPEND; import static android.system.OsConstants.O_CREAT; @@ -37,6 +38,7 @@ import static android.system.OsConstants.SPLICE_F_MORE; import static android.system.OsConstants.SPLICE_F_MOVE; import static android.system.OsConstants.S_ISFIFO; import static android.system.OsConstants.S_ISREG; +import static android.system.OsConstants.S_ISSOCK; import static android.system.OsConstants.W_OK; import android.annotation.NonNull; @@ -474,6 +476,8 @@ public final class FileUtils { } } else if (S_ISFIFO(st_in.st_mode) || S_ISFIFO(st_out.st_mode)) { return copyInternalSplice(in, out, count, signal, executor, listener); + } else if (S_ISSOCK(st_in.st_mode) || S_ISSOCK(st_out.st_mode)) { + return copyInternalSpliceSocket(in, out, count, signal, executor, listener); } } catch (ErrnoException e) { throw e.rethrowAsIOException(); @@ -525,6 +529,86 @@ public final class FileUtils { } return progress; } + /** + * Requires one of input or output to be a socket file. + * + * @hide + */ + @VisibleForTesting + public static long copyInternalSpliceSocket(FileDescriptor in, FileDescriptor out, long count, + CancellationSignal signal, Executor executor, ProgressListener listener) + throws ErrnoException { + long progress = 0; + long checkpoint = 0; + long countToRead = count; + long countInPipe = 0; + long t; + + FileDescriptor[] pipes = Os.pipe(); + + while (countToRead > 0 || countInPipe > 0) { + if (countToRead > 0) { + t = Os.splice(in, null, pipes[1], null, Math.min(countToRead, COPY_CHECKPOINT_BYTES), + SPLICE_F_MOVE | SPLICE_F_MORE); + if (t < 0) { + // splice error + Slog.e(TAG, "splice error, fdIn --> pipe, copy size:" + count + + ", copied:" + progress + + ", read:" + (count - countToRead) + + ", in pipe:" + countInPipe); + break; + } else if (t == 0) { + // end of input, input count larger than real size + Slog.w(TAG, "Reached the end of the input file. The size to be copied exceeds the actual size, copy size:" + count + + ", copied:" + progress + + ", read:" + (count - countToRead) + + ", in pipe:" + countInPipe); + countToRead = 0; + } else { + countInPipe += t; + countToRead -= t; + } + } + + if (countInPipe > 0) { + t = Os.splice(pipes[0], null, out, null, Math.min(countInPipe, COPY_CHECKPOINT_BYTES), + SPLICE_F_MOVE | SPLICE_F_MORE); + // The data is already in the pipeline, so the return value will not be zero. + // If it is 0, it means an error has occurred. So here use t<=0. + if (t <= 0) { + Slog.e(TAG, "splice error, pipe --> fdOut, copy size:" + count + + ", copied:" + progress + + ", read:" + (count - countToRead) + + ", in pipe: " + countInPipe); + throw new ErrnoException("splice, pipe --> fdOut", EIO); + } else { + progress += t; + checkpoint += t; + countInPipe -= t; + } + } + + if (checkpoint >= COPY_CHECKPOINT_BYTES) { + if (signal != null) { + signal.throwIfCanceled(); + } + if (executor != null && listener != null) { + final long progressSnapshot = progress; + executor.execute(() -> { + listener.onProgress(progressSnapshot); + }); + } + checkpoint = 0; + } + } + if (executor != null && listener != null) { + final long progressSnapshot = progress; + executor.execute(() -> { + listener.onProgress(progressSnapshot); + }); + } + return progress; + } /** * Requires both input and output to be a regular file. diff --git a/core/java/android/os/VintfObject.java b/core/java/android/os/VintfObject.java index 4fc5131617b2..505655775239 100644 --- a/core/java/android/os/VintfObject.java +++ b/core/java/android/os/VintfObject.java @@ -31,6 +31,10 @@ public class VintfObject { private static final String LOG_TAG = "VintfObject"; + static { + System.loadLibrary("vintf_jni"); + } + /** * Slurps all device information (both manifests and both matrices) * and report them. diff --git a/core/java/android/os/VintfRuntimeInfo.java b/core/java/android/os/VintfRuntimeInfo.java index f17039ba9bf4..e729063d6763 100644 --- a/core/java/android/os/VintfRuntimeInfo.java +++ b/core/java/android/os/VintfRuntimeInfo.java @@ -28,6 +28,10 @@ public class VintfRuntimeInfo { private VintfRuntimeInfo() {} + static { + System.loadLibrary("vintf_jni"); + } + /** * @return /sys/fs/selinux/policyvers, via security_policyvers() native call * diff --git a/core/java/android/permission/flags.aconfig b/core/java/android/permission/flags.aconfig index 39b6aeb814f6..8c7050176506 100644 --- a/core/java/android/permission/flags.aconfig +++ b/core/java/android/permission/flags.aconfig @@ -86,3 +86,11 @@ flag { description: "This flag is used to enabled the Wallet Role for all users on the device" bug: "283989236" } + +flag { + name: "signature_permission_allowlist_enabled" + is_fixed_read_only: true + namespace: "permissions" + description: "Enable signature permission allowlist" + bug: "308573169" +} diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index ab98c94cba73..d946430f18af 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -3243,9 +3243,17 @@ public final class Settings { private static final String NAME_EQ_PLACEHOLDER = "name=?"; + // Cached values of queried settings. + // Key is the setting's name, value is the setting's value. // Must synchronize on 'this' to access mValues and mValuesVersion. private final ArrayMap<String, String> mValues = new ArrayMap<>(); + // Cached values for queried prefixes. + // Key is the prefix, value is all of the settings under the prefix, mapped from a setting's + // name to a setting's value. The name string doesn't include the prefix. + // Must synchronize on 'this' to access. + private final ArrayMap<String, ArrayMap<String, String>> mPrefixToValues = new ArrayMap<>(); + private final Uri mUri; @UnsupportedAppUsage private final ContentProviderHolder mProviderHolder; @@ -3592,15 +3600,13 @@ public final class Settings { || applicationInfo.isSignedWithPlatformKey(); } - private ArrayMap<String, String> getStringsForPrefixStripPrefix( - ContentResolver cr, String prefix, String[] names) { + private Map<String, String> getStringsForPrefixStripPrefix( + ContentResolver cr, String prefix, List<String> names) { String namespace = prefix.substring(0, prefix.length() - 1); ArrayMap<String, String> keyValues = new ArrayMap<>(); int substringLength = prefix.length(); - int currentGeneration = -1; boolean needsGenerationTracker = false; - synchronized (NameValueCache.this) { final GenerationTracker generationTracker = mGenerationTrackers.get(prefix); if (generationTracker != null) { @@ -3614,40 +3620,24 @@ public final class Settings { // generation tracker and request a new one generationTracker.destroy(); mGenerationTrackers.remove(prefix); - for (int i = mValues.size() - 1; i >= 0; i--) { - String key = mValues.keyAt(i); - if (key.startsWith(prefix)) { - mValues.remove(key); - } - } + mPrefixToValues.remove(prefix); needsGenerationTracker = true; } else { - boolean prefixCached = mValues.containsKey(prefix); - if (prefixCached) { - if (DEBUG) { - Log.i(TAG, "Cache hit for prefix:" + prefix); - } - if (names.length > 0) { + final ArrayMap<String, String> cachedSettings = mPrefixToValues.get(prefix); + if (cachedSettings != null) { + if (!names.isEmpty()) { for (String name : names) { - // mValues can contain "null" values, need to use containsKey. - if (mValues.containsKey(name)) { + // The cache can contain "null" values, need to use containsKey. + if (cachedSettings.containsKey(name)) { keyValues.put( - name.substring(substringLength), - mValues.get(name)); + name, + cachedSettings.get(name)); } } } else { - for (int i = 0; i < mValues.size(); ++i) { - String key = mValues.keyAt(i); - // Explicitly exclude the prefix as it is only there to - // signal that the prefix has been cached. - if (key.startsWith(prefix) && !key.equals(prefix)) { - String value = mValues.valueAt(i); - keyValues.put( - key.substring(substringLength), - value); - } - } + keyValues.putAll(cachedSettings); + // Remove the hack added for the legacy behavior. + keyValues.remove(""); } return keyValues; } @@ -3657,7 +3647,6 @@ public final class Settings { needsGenerationTracker = true; } } - if (mCallListCommand == null) { // No list command specified, return empty map return keyValues; @@ -3702,20 +3691,23 @@ public final class Settings { } // All flags for the namespace - Map<String, String> flagsToValues = + HashMap<String, String> flagsToValues = (HashMap) b.getSerializable(Settings.NameValueTable.VALUE, java.util.HashMap.class); + if (flagsToValues == null) { + return keyValues; + } // Only the flags requested by the caller - if (names.length > 0) { + if (!names.isEmpty()) { for (String name : names) { // flagsToValues can contain "null" values, need to use containsKey. - if (flagsToValues.containsKey(name)) { + final String key = Config.createCompositeName(namespace, name); + if (flagsToValues.containsKey(key)) { keyValues.put( - name.substring(substringLength), - flagsToValues.get(name)); + name, + flagsToValues.get(key)); } } } else { - keyValues.ensureCapacity(keyValues.size() + flagsToValues.size()); for (Map.Entry<String, String> flag : flagsToValues.entrySet()) { keyValues.put( flag.getKey().substring(substringLength), @@ -3751,10 +3743,18 @@ public final class Settings { if (DEBUG) { Log.i(TAG, "Updating cache for prefix:" + prefix); } - // cache the complete list of flags for the namespace - mValues.putAll(flagsToValues); - // Adding the prefix as a signal that the prefix is cached. - mValues.put(prefix, null); + // Cache the complete list of flags for the namespace for bulk queries. + // In this cached list, the setting's name doesn't include the prefix. + ArrayMap<String, String> namesToValues = + new ArrayMap<>(flagsToValues.size() + 1); + for (Map.Entry<String, String> flag : flagsToValues.entrySet()) { + namesToValues.put( + flag.getKey().substring(substringLength), + flag.getValue()); + } + // Legacy behavior, we return <"", null> when queried with name = "" + namesToValues.put("", null); + mPrefixToValues.put(prefix, namesToValues); } } return keyValues; @@ -19945,16 +19945,9 @@ public final class Settings { @RequiresPermission(Manifest.permission.READ_DEVICE_CONFIG) public static Map<String, String> getStrings(@NonNull ContentResolver resolver, @NonNull String namespace, @NonNull List<String> names) { - String[] compositeNames = new String[names.size()]; - for (int i = 0, size = names.size(); i < size; ++i) { - compositeNames[i] = createCompositeName(namespace, names.get(i)); - } - String prefix = createPrefix(namespace); - ArrayMap<String, String> keyValues = sNameValueCache.getStringsForPrefixStripPrefix( - resolver, prefix, compositeNames); - return keyValues; + return sNameValueCache.getStringsForPrefixStripPrefix(resolver, prefix, names); } /** @@ -20276,7 +20269,7 @@ public final class Settings { } } - private static String createCompositeName(@NonNull String namespace, @NonNull String name) { + static String createCompositeName(@NonNull String namespace, @NonNull String name) { Preconditions.checkNotNull(namespace); Preconditions.checkNotNull(name); var sb = new StringBuilder(namespace.length() + 1 + name.length()); diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java index c479877fe98e..9895551a8672 100644 --- a/core/java/android/service/notification/ZenModeConfig.java +++ b/core/java/android/service/notification/ZenModeConfig.java @@ -185,7 +185,13 @@ public class ZenModeConfig implements Parcelable { SUPPRESSED_EFFECT_SCREEN_OFF | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_PEEK | SUPPRESSED_EFFECT_AMBIENT; - public static final int XML_VERSION = 8; + // ZenModeConfig XML versions distinguishing key changes. + public static final int XML_VERSION_ZEN_UPGRADE = 8; + public static final int XML_VERSION_MODES_API = 11; + + // TODO: b/310620812 - Update XML_VERSION and update default_zen_config.xml accordingly when + // modes_api is inlined. + private static final int XML_VERSION = 10; public static final String ZEN_TAG = "zen"; private static final String ZEN_ATT_VERSION = "version"; private static final String ZEN_ATT_USER = "user"; @@ -586,6 +592,10 @@ public class ZenModeConfig implements Parcelable { } } + public static int getCurrentXmlVersion() { + return Flags.modesApi() ? XML_VERSION_MODES_API : XML_VERSION; + } + public static ZenModeConfig readXml(TypedXmlPullParser parser) throws XmlPullParserException, IOException { int type = parser.getEventType(); @@ -593,7 +603,7 @@ public class ZenModeConfig implements Parcelable { String tag = parser.getName(); if (!ZEN_TAG.equals(tag)) return null; final ZenModeConfig rt = new ZenModeConfig(); - rt.version = safeInt(parser, ZEN_ATT_VERSION, XML_VERSION); + rt.version = safeInt(parser, ZEN_ATT_VERSION, getCurrentXmlVersion()); rt.user = safeInt(parser, ZEN_ATT_USER, rt.user); boolean readSuppressedEffects = false; while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) { @@ -707,14 +717,16 @@ public class ZenModeConfig implements Parcelable { /** * Writes XML of current ZenModeConfig * @param out serializer - * @param version uses XML_VERSION if version is null + * @param version uses the current XML version if version is null * @throws IOException */ + public void writeXml(TypedXmlSerializer out, Integer version, boolean forBackup) throws IOException { + int xmlVersion = getCurrentXmlVersion(); out.startTag(null, ZEN_TAG); out.attribute(null, ZEN_ATT_VERSION, version == null - ? Integer.toString(XML_VERSION) : Integer.toString(version)); + ? Integer.toString(xmlVersion) : Integer.toString(version)); out.attributeInt(null, ZEN_ATT_USER, user); out.startTag(null, ALLOW_TAG); out.attributeBoolean(null, ALLOW_ATT_CALLS, allowCalls); diff --git a/core/java/android/service/notification/ZenPolicy.aidl b/core/java/android/service/notification/ZenPolicy.aidl new file mode 100644 index 000000000000..b56f5c6989bf --- /dev/null +++ b/core/java/android/service/notification/ZenPolicy.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.service.notification; + +parcelable ZenPolicy;
\ No newline at end of file diff --git a/core/java/android/service/notification/ZenPolicy.java b/core/java/android/service/notification/ZenPolicy.java index fb491d010f54..d8318a6bee7c 100644 --- a/core/java/android/service/notification/ZenPolicy.java +++ b/core/java/android/service/notification/ZenPolicy.java @@ -1422,6 +1422,54 @@ public final class ZenPolicy implements Parcelable { } /** + * Overwrites any policy values in this ZenPolicy with set values from newPolicy and + * returns a copy of the resulting ZenPolicy. + * Unlike apply(), values set in newPolicy will always be kept over pre-existing + * fields. Any values in newPolicy that are not set keep their currently set values. + * + * @hide + */ + @TestApi + @FlaggedApi(Flags.FLAG_MODES_API) + public @NonNull ZenPolicy overwrittenWith(@Nullable ZenPolicy newPolicy) { + ZenPolicy result = this.copy(); + + if (newPolicy == null) { + return result; + } + + // set priority categories + for (int category = 0; category < mPriorityCategories.size(); category++) { + @State int newState = newPolicy.mPriorityCategories.get(category); + if (newState != STATE_UNSET) { + result.mPriorityCategories.set(category, newState); + + if (category == PRIORITY_CATEGORY_MESSAGES) { + result.mPriorityMessages = newPolicy.mPriorityMessages; + } else if (category == PRIORITY_CATEGORY_CALLS) { + result.mPriorityCalls = newPolicy.mPriorityCalls; + } else if (category == PRIORITY_CATEGORY_CONVERSATIONS) { + result.mConversationSenders = newPolicy.mConversationSenders; + } + } + } + + // set visual effects + for (int visualEffect = 0; visualEffect < mVisualEffects.size(); visualEffect++) { + if (newPolicy.mVisualEffects.get(visualEffect) != STATE_UNSET) { + result.mVisualEffects.set(visualEffect, newPolicy.mVisualEffects.get(visualEffect)); + } + } + + // set allowed channels + if (newPolicy.mAllowChannels != CHANNEL_POLICY_UNSET) { + result.mAllowChannels = newPolicy.mAllowChannels; + } + + return result; + } + + /** * @hide */ public void dumpDebug(ProtoOutputStream proto, long fieldId) { diff --git a/core/java/android/service/quickaccesswallet/QuickAccessWalletServiceInfo.java b/core/java/android/service/quickaccesswallet/QuickAccessWalletServiceInfo.java index ce38bb823fb3..e6d8fd0e2f2b 100644 --- a/core/java/android/service/quickaccesswallet/QuickAccessWalletServiceInfo.java +++ b/core/java/android/service/quickaccesswallet/QuickAccessWalletServiceInfo.java @@ -19,6 +19,7 @@ package android.service.quickaccesswallet; import android.Manifest; import android.annotation.NonNull; import android.annotation.Nullable; +import android.app.role.RoleManager; import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; @@ -30,6 +31,7 @@ import android.content.res.Resources; import android.content.res.TypedArray; import android.content.res.XmlResourceParser; import android.graphics.drawable.Drawable; +import android.os.Binder; import android.provider.Settings; import android.text.TextUtils; import android.util.AttributeSet; @@ -69,12 +71,17 @@ class QuickAccessWalletServiceInfo { @Nullable static QuickAccessWalletServiceInfo tryCreate(@NonNull Context context) { - ComponentName defaultPaymentApp = getDefaultPaymentApp(context); - if (defaultPaymentApp == null) { - return null; + String defaultAppPackageName = getDefaultWalletApp(context); + + if (defaultAppPackageName == null) { + ComponentName defaultPaymentApp = getDefaultPaymentApp(context); + if (defaultPaymentApp == null) { + return null; + } + defaultAppPackageName = defaultPaymentApp.getPackageName(); } - ServiceInfo serviceInfo = getWalletServiceInfo(context, defaultPaymentApp.getPackageName()); + ServiceInfo serviceInfo = getWalletServiceInfo(context, defaultAppPackageName); if (serviceInfo == null) { return null; } @@ -92,6 +99,20 @@ class QuickAccessWalletServiceInfo { return new QuickAccessWalletServiceInfo(serviceInfo, metadata, tileServiceMetadata); } + private static String getDefaultWalletApp(Context context) { + final long token = Binder.clearCallingIdentity(); + try { + RoleManager roleManager = context.getSystemService(RoleManager.class); + if (roleManager.isRoleAvailable(RoleManager.ROLE_WALLET)) { + List<String> roleHolders = roleManager.getRoleHolders(RoleManager.ROLE_WALLET); + return roleHolders.isEmpty() ? null : roleHolders.get(0); + } + } finally { + Binder.restoreCallingIdentity(token); + } + return null; + } + private static ComponentName getDefaultPaymentApp(Context context) { ContentResolver cr = context.getContentResolver(); String comp = Settings.Secure.getString(cr, Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT); diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java index 1a2be15b2e8d..76e0c259b38f 100644 --- a/core/java/android/service/wallpaper/WallpaperService.java +++ b/core/java/android/service/wallpaper/WallpaperService.java @@ -16,6 +16,7 @@ package android.service.wallpaper; +import static android.app.WallpaperManager.COMMAND_DISPLAY_SWITCH; import static android.app.WallpaperManager.COMMAND_FREEZE; import static android.app.WallpaperManager.COMMAND_UNFREEZE; import static android.app.WallpaperManager.SetWallpaperFlags; @@ -153,6 +154,7 @@ public abstract class WallpaperService extends Service { static final boolean DEBUG = false; static final float MIN_PAGE_ALLOWED_MARGIN = .05f; private static final int MIN_BITMAP_SCREENSHOT_WIDTH = 64; + private static final long PRESERVE_VISIBLE_TIMEOUT_MS = 1000; private static final long DEFAULT_UPDATE_SCREENSHOT_DURATION = 60 * 1000; //Once per minute private static final @NonNull RectF LOCAL_COLOR_BOUNDS = new RectF(0, 0, 1, 1); @@ -165,6 +167,7 @@ public abstract class WallpaperService extends Service { private static final int MSG_UPDATE_SURFACE = 10000; private static final int MSG_VISIBILITY_CHANGED = 10010; + private static final int MSG_REFRESH_VISIBILITY = 10011; private static final int MSG_WALLPAPER_OFFSETS = 10020; private static final int MSG_WALLPAPER_COMMAND = 10025; @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) @@ -248,6 +251,11 @@ public abstract class WallpaperService extends Service { */ private boolean mIsScreenTurningOn; boolean mReportedVisible; + /** + * This is used with {@link #PRESERVE_VISIBLE_TIMEOUT_MS} to avoid intermediate visibility + * changes if the display may be toggled in a short time, e.g. display switch. + */ + boolean mPreserveVisible; boolean mDestroyed; // Set to true after receiving WallpaperManager#COMMAND_FREEZE. It's reset back to false // after receiving WallpaperManager#COMMAND_UNFREEZE. COMMAND_FREEZE is fully applied once @@ -1084,6 +1092,9 @@ public abstract class WallpaperService extends Service { if (pendingCount != 0) { out.print(prefix); out.print("mPendingResizeCount="); out.println(pendingCount); } + if (mPreserveVisible) { + out.print(prefix); out.print("mPreserveVisible=true"); + } synchronized (mLock) { out.print(prefix); out.print("mPendingXOffset="); out.print(mPendingXOffset); out.print(" mPendingXOffset="); out.println(mPendingXOffset); @@ -1643,7 +1654,8 @@ public abstract class WallpaperService extends Service { ? false : mIWallpaperEngine.mInfo.supportsAmbientMode(); // Report visibility only if display is fully on or wallpaper supports ambient mode. - boolean visible = mVisible && (displayFullyOn || supportsAmbientMode); + final boolean visible = (mVisible && (displayFullyOn || supportsAmbientMode)) + || mPreserveVisible; if (DEBUG) { Log.v( TAG, @@ -2080,6 +2092,9 @@ public abstract class WallpaperService extends Service { if (!mDestroyed) { if (COMMAND_FREEZE.equals(cmd.action) || COMMAND_UNFREEZE.equals(cmd.action)) { updateFrozenState(/* frozenRequested= */ !COMMAND_UNFREEZE.equals(cmd.action)); + } else if (COMMAND_DISPLAY_SWITCH.equals(cmd.action)) { + handleDisplaySwitch(cmd.z == 1 /* startToSwitch */); + return; } result = onCommand(cmd.action, cmd.x, cmd.y, cmd.z, cmd.extras, cmd.sync); @@ -2095,6 +2110,23 @@ public abstract class WallpaperService extends Service { } } + private void handleDisplaySwitch(boolean startToSwitch) { + if (startToSwitch && mReportedVisible) { + // The display may be off/on in a short time when the display is switching. + // Keep the visible state until onScreenTurnedOn or !startToSwitch is received, so + // the rendering thread can be active to redraw in time when receiving size change. + mPreserveVisible = true; + mCaller.removeMessages(MSG_REFRESH_VISIBILITY); + mCaller.sendMessageDelayed(mCaller.obtainMessage(MSG_REFRESH_VISIBILITY), + PRESERVE_VISIBLE_TIMEOUT_MS); + } else if (!startToSwitch && mPreserveVisible) { + // The switch is finished, so restore to actual visibility. + mPreserveVisible = false; + mCaller.removeMessages(MSG_REFRESH_VISIBILITY); + reportVisibility(false /* forceReport */); + } + } + private void updateFrozenState(boolean frozenRequested) { if (mIWallpaperEngine.mInfo == null // Procees the unfreeze command in case the wallaper became static while @@ -2638,6 +2670,10 @@ public abstract class WallpaperService extends Service { + ": " + message.arg1); mEngine.doVisibilityChanged(message.arg1 != 0); break; + case MSG_REFRESH_VISIBILITY: + mEngine.mPreserveVisible = false; + mEngine.reportVisibility(false /* forceReport */); + break; case MSG_UPDATE_SCREEN_TURNING_ON: if (DEBUG) { Log.v(TAG, diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java index 8935ab38451a..0a813a3edb1f 100644 --- a/core/java/android/telephony/TelephonyRegistryManager.java +++ b/core/java/android/telephony/TelephonyRegistryManager.java @@ -38,6 +38,7 @@ import android.telephony.Annotation.PreciseDisconnectCauses; import android.telephony.Annotation.RadioPowerState; import android.telephony.Annotation.SimActivationState; import android.telephony.Annotation.SrvccState; +import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener; import android.telephony.TelephonyManager.CarrierPrivilegesCallback; import android.telephony.emergency.EmergencyNumber; import android.telephony.ims.ImsCallSession; @@ -116,14 +117,15 @@ public class TelephonyRegistryManager { } /** - * Register for changes to the list of active {@link SubscriptionInfo} records or to the - * individual records themselves. When a change occurs the onSubscriptionsChanged method of - * the listener will be invoked immediately if there has been a notification. The - * onSubscriptionChanged method will also be triggered once initially when calling this - * function. + * Register for changes to the list of {@link SubscriptionInfo} records or to the + * individual records (active or inactive) themselves. When a change occurs, the + * {@link OnSubscriptionsChangedListener#onSubscriptionsChanged()} method of + * the listener will be invoked immediately. The + * {@link OnSubscriptionsChangedListener#onSubscriptionsChanged()} method will also be invoked + * once initially when calling this method. * - * @param listener an instance of {@link SubscriptionManager.OnSubscriptionsChangedListener} - * with onSubscriptionsChanged overridden. + * @param listener an instance of {@link OnSubscriptionsChangedListener} with + * {@link OnSubscriptionsChangedListener#onSubscriptionsChanged()} overridden. * @param executor the executor that will execute callbacks. * @hide */ diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java index eca848ae1ea3..1ea80f146b0b 100644 --- a/core/java/android/text/Layout.java +++ b/core/java/android/text/Layout.java @@ -152,7 +152,8 @@ public abstract class Layout { /** @hide */ @IntDef(prefix = { "JUSTIFICATION_MODE_" }, value = { LineBreaker.JUSTIFICATION_MODE_NONE, - LineBreaker.JUSTIFICATION_MODE_INTER_WORD + LineBreaker.JUSTIFICATION_MODE_INTER_WORD, + LineBreaker.JUSTIFICATION_MODE_INTER_CHARACTER, }) @Retention(RetentionPolicy.SOURCE) public @interface JustificationMode {} @@ -168,6 +169,13 @@ public abstract class Layout { public static final int JUSTIFICATION_MODE_INTER_WORD = LineBreaker.JUSTIFICATION_MODE_INTER_WORD; + /** + * Value for justification mode indicating the text is justified by stretching letter spacing. + */ + @FlaggedApi(FLAG_INTER_CHARACTER_JUSTIFICATION) + public static final int JUSTIFICATION_MODE_INTER_CHARACTER = + LineBreaker.JUSTIFICATION_MODE_INTER_CHARACTER; + /* * Line spacing multiplier for default line spacing. */ @@ -809,7 +817,7 @@ public abstract class Layout { getEllipsisStart(lineNum) + getEllipsisCount(lineNum), isFallbackLineSpacingEnabled()); if (justify) { - tl.justify(right - left - indentWidth); + tl.justify(mJustificationMode, right - left - indentWidth); } tl.draw(canvas, x, ltop, lbaseline, lbottom); } @@ -1058,7 +1066,7 @@ public abstract class Layout { getEllipsisStart(line), getEllipsisStart(line) + getEllipsisCount(line), isFallbackLineSpacingEnabled()); if (isJustificationRequired(line)) { - tl.justify(getJustifyWidth(line)); + tl.justify(mJustificationMode, getJustifyWidth(line)); } tl.metrics(null, rectF, false, null); @@ -1794,7 +1802,7 @@ public abstract class Layout { getEllipsisStart(line), getEllipsisStart(line) + getEllipsisCount(line), isFallbackLineSpacingEnabled()); if (isJustificationRequired(line)) { - tl.justify(getJustifyWidth(line)); + tl.justify(mJustificationMode, getJustifyWidth(line)); } final float width = tl.metrics(null, null, mUseBoundsForWidth, null); TextLine.recycle(tl); @@ -1882,7 +1890,7 @@ public abstract class Layout { getEllipsisStart(line), getEllipsisStart(line) + getEllipsisCount(line), isFallbackLineSpacingEnabled()); if (isJustificationRequired(line)) { - tl.justify(getJustifyWidth(line)); + tl.justify(mJustificationMode, getJustifyWidth(line)); } final float width = tl.metrics(null, null, mUseBoundsForWidth, null); TextLine.recycle(tl); diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java index 2175b47e149e..224e5d8f7712 100644 --- a/core/java/android/text/TextLine.java +++ b/core/java/android/text/TextLine.java @@ -100,9 +100,25 @@ public class TextLine { // Additional width of whitespace for justification. This value is per whitespace, thus // the line width will increase by mAddedWidthForJustify x (number of stretchable whitespaces). - private float mAddedWidthForJustify; + private float mAddedWordSpacingInPx; + private float mAddedLetterSpacingInPx; private boolean mIsJustifying; + @VisibleForTesting + public float getAddedWordSpacingInPx() { + return mAddedWordSpacingInPx; + } + + @VisibleForTesting + public float getAddedLetterSpacingInPx() { + return mAddedLetterSpacingInPx; + } + + @VisibleForTesting + public boolean isJustifying() { + return mIsJustifying; + } + private final TextPaint mWorkPaint = new TextPaint(); private final TextPaint mActivePaint = new TextPaint(); @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) @@ -259,7 +275,7 @@ public class TextLine { } } mTabs = tabStops; - mAddedWidthForJustify = 0; + mAddedWordSpacingInPx = 0; mIsJustifying = false; mEllipsisStart = ellipsisStart != ellipsisEnd ? ellipsisStart : 0; @@ -274,19 +290,42 @@ public class TextLine { * Justify the line to the given width. */ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public void justify(float justifyWidth) { + public void justify(@Layout.JustificationMode int justificationMode, float justifyWidth) { int end = mLen; while (end > 0 && isLineEndSpace(mText.charAt(mStart + end - 1))) { end--; } - final int spaces = countStretchableSpaces(0, end); - if (spaces == 0) { - // There are no stretchable spaces, so we can't help the justification by adding any - // width. - return; + if (justificationMode == Layout.JUSTIFICATION_MODE_INTER_WORD) { + float width = Math.abs(measure(end, false, null, null, null)); + final int spaces = countStretchableSpaces(0, end); + if (spaces == 0) { + // There are no stretchable spaces, so we can't help the justification by adding any + // width. + return; + } + mAddedWordSpacingInPx = (justifyWidth - width) / spaces; + mAddedLetterSpacingInPx = 0; + } else { // justificationMode == Layout.JUSTIFICATION_MODE_INTER_CHARACTER + LineInfo lineInfo = new LineInfo(); + float width = Math.abs(measure(end, false, null, null, lineInfo)); + + int lettersCount = lineInfo.getClusterCount(); + if (lettersCount < 2) { + return; + } + mAddedLetterSpacingInPx = (justifyWidth - width) / (lettersCount - 1); + if (mAddedLetterSpacingInPx > 0.03) { + // If the letter spacing is more than 0.03em, the ligatures are automatically + // disabled, so re-calculate everything without ligatures. + final String oldFontFeatures = mPaint.getFontFeatureSettings(); + mPaint.setFontFeatureSettings(oldFontFeatures + ", \"liga\" off, \"cliga\" off"); + width = Math.abs(measure(end, false, null, null, lineInfo)); + lettersCount = lineInfo.getClusterCount(); + mAddedLetterSpacingInPx = (justifyWidth - width) / (lettersCount - 1); + mPaint.setFontFeatureSettings(oldFontFeatures); + } + mAddedWordSpacingInPx = 0; } - final float width = Math.abs(measure(end, false, null, null, null)); - mAddedWidthForJustify = (justifyWidth - width) / spaces; mIsJustifying = true; } @@ -529,6 +568,9 @@ public class TextLine { throw new IndexOutOfBoundsException( "offset(" + offset + ") should be less than line limit(" + mLen + ")"); } + if (lineInfo != null) { + lineInfo.setClusterCount(0); + } final int target = trailing ? offset - 1 : offset; if (target < 0) { return 0; @@ -1076,7 +1118,8 @@ public class TextLine { TextPaint wp = mWorkPaint; wp.set(mPaint); if (mIsJustifying) { - wp.setWordSpacing(mAddedWidthForJustify); + wp.setWordSpacing(mAddedWordSpacingInPx); + wp.setLetterSpacing(mAddedLetterSpacingInPx / wp.getTextSize()); // Convert to Em } int spanStart = runStart; @@ -1277,7 +1320,8 @@ public class TextLine { @Nullable float[] advances, int advancesIndex, @Nullable LineInfo lineInfo, int runFlag) { if (mIsJustifying) { - wp.setWordSpacing(mAddedWidthForJustify); + wp.setWordSpacing(mAddedWordSpacingInPx); + wp.setLetterSpacing(mAddedLetterSpacingInPx / wp.getTextSize()); // Convert to Em } // Get metrics first (even for empty strings or "0" width runs) if (drawBounds != null && fmi == null) { diff --git a/core/java/android/text/flags/flags.aconfig b/core/java/android/text/flags/flags.aconfig index a1885ae616e1..bf1a59625c93 100644 --- a/core/java/android/text/flags/flags.aconfig +++ b/core/java/android/text/flags/flags.aconfig @@ -82,3 +82,10 @@ flag { description: "A feature flag that implement inter character justification." bug: "283193133" } + +flag { + name: "escape_clears_focus" + namespace: "text" + description: "Feature flag for clearing focus when the escape key is pressed." + bug: "312921137" +} diff --git a/core/java/android/view/PointerIcon.java b/core/java/android/view/PointerIcon.java index 7800c28ae089..9b21b765a874 100644 --- a/core/java/android/view/PointerIcon.java +++ b/core/java/android/view/PointerIcon.java @@ -32,7 +32,6 @@ import android.graphics.RectF; import android.graphics.drawable.AnimationDrawable; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; -import android.hardware.display.DisplayManager; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; @@ -156,14 +155,12 @@ public final class PointerIcon implements Parcelable { */ public static final int TYPE_DEFAULT = TYPE_ARROW; - private static final PointerIcon gNullIcon = new PointerIcon(TYPE_NULL); - private static final SparseArray<SparseArray<PointerIcon>> gSystemIconsByDisplay = - new SparseArray<SparseArray<PointerIcon>>(); - private static boolean sUseLargeIcons = false; + // A cache of the system icons used by the app, used to avoid creating a new PointerIcon object + // every time we need to resolve the icon (i.e. on each input event). + private static final SparseArray<PointerIcon> SYSTEM_ICONS = new SparseArray<>(); @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) private final int mType; - private int mSystemIconResourceId; @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) private Bitmap mBitmap; @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) @@ -177,44 +174,12 @@ public final class PointerIcon implements Parcelable { @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) private int mDurationPerFrame; - /** - * Listener for displays lifecycle. - * @hide - */ - private static DisplayManager.DisplayListener sDisplayListener; - private PointerIcon(int type) { mType = type; } /** - * Gets a special pointer icon that has no bitmap. - * - * @return The null pointer icon. - * - * @see #TYPE_NULL - * @hide - */ - public static @NonNull PointerIcon getNullIcon() { - return gNullIcon; - } - - /** - * Gets the default pointer icon. - * - * @param context The context. - * @return The default pointer icon. - * - * @throws IllegalArgumentException if context is null. - * @hide - */ - public static @NonNull PointerIcon getDefaultIcon(@NonNull Context context) { - return getSystemIcon(context, TYPE_DEFAULT); - } - - /** * Gets a system pointer icon for the given type. - * If typeis not recognized, returns the default pointer icon. * * @param context The context. * @param type The pointer icon type. @@ -223,32 +188,42 @@ public final class PointerIcon implements Parcelable { * @throws IllegalArgumentException if context is null. */ public static @NonNull PointerIcon getSystemIcon(@NonNull Context context, int type) { - // TODO(b/293587049): Pointer Icon Refactor: There is no need to load the system - // icon resource into memory outside of system server. Remove the need to load - // resources when getting a system icon. if (context == null) { + // We no longer use the context to resolve the system icon resource here, because the + // system will use its own context to do the type-to-resource resolution and cache it + // for use across different apps. Therefore, apps cannot customize the resource of a + // system icon. To avoid changing the public API, we keep the context parameter + // requirement. throw new IllegalArgumentException("context must not be null"); } + return getSystemIcon(type); + } - if (type == TYPE_NULL) { - return gNullIcon; + private static @NonNull PointerIcon getSystemIcon(int type) { + if (type == TYPE_CUSTOM) { + throw new IllegalArgumentException("cannot get system icon for TYPE_CUSTOM"); } - - if (sDisplayListener == null) { - registerDisplayListener(context); + PointerIcon icon = SYSTEM_ICONS.get(type); + if (icon == null) { + icon = new PointerIcon(type); + SYSTEM_ICONS.put(type, icon); } + return icon; + } - final int displayId = context.getDisplayId(); - SparseArray<PointerIcon> systemIcons = gSystemIconsByDisplay.get(displayId); - if (systemIcons == null) { - systemIcons = new SparseArray<>(); - gSystemIconsByDisplay.put(displayId, systemIcons); + /** + * Get a system icon with its resources loaded. + * This should only be used by the system for drawing icons to the screen. + * @hide + */ + public static @NonNull PointerIcon getLoadedSystemIcon(@NonNull Context context, int type, + boolean useLargeIcons) { + if (type == TYPE_NOT_SPECIFIED) { + throw new IllegalStateException("Cannot load icon for type TYPE_NOT_SPECIFIED"); } - PointerIcon icon = systemIcons.get(type); - // Reload if not in the same display. - if (icon != null) { - return icon; + if (type == TYPE_CUSTOM) { + throw new IllegalArgumentException("Custom icons must be loaded when they're created"); } int typeIndex = getSystemIconTypeIndex(type); @@ -256,8 +231,9 @@ public final class PointerIcon implements Parcelable { typeIndex = getSystemIconTypeIndex(TYPE_DEFAULT); } - int defStyle = sUseLargeIcons ? - com.android.internal.R.style.LargePointer : com.android.internal.R.style.Pointer; + final int defStyle = useLargeIcons + ? com.android.internal.R.style.LargePointer + : com.android.internal.R.style.Pointer; TypedArray a = context.obtainStyledAttributes(null, com.android.internal.R.styleable.Pointer, 0, defStyle); @@ -266,26 +242,19 @@ public final class PointerIcon implements Parcelable { if (resourceId == -1) { Log.w(TAG, "Missing theme resources for pointer icon type " + type); - return type == TYPE_DEFAULT ? gNullIcon : getSystemIcon(context, TYPE_DEFAULT); + return type == TYPE_DEFAULT + ? getSystemIcon(TYPE_NULL) + : getLoadedSystemIcon(context, TYPE_DEFAULT, useLargeIcons); } - icon = new PointerIcon(type); - if ((resourceId & 0xff000000) == 0x01000000) { - icon.mSystemIconResourceId = resourceId; - } else { - icon.loadResource(context, context.getResources(), resourceId); - } - systemIcons.append(type, icon); + final PointerIcon icon = new PointerIcon(type); + icon.loadResource(context, context.getResources(), resourceId); return icon; } - /** - * Updates wheter accessibility large icons are used or not. - * @hide - */ - public static void setUseLargeIcons(boolean use) { - sUseLargeIcons = use; - gSystemIconsByDisplay.clear(); + private boolean isLoaded() { + return mBitmap != null && mHotSpotX >= 0 && mHotSpotX < mBitmap.getWidth() && mHotSpotY >= 0 + && mHotSpotY < mBitmap.getHeight(); } /** @@ -346,78 +315,53 @@ public final class PointerIcon implements Parcelable { return icon; } - /** - * Loads the bitmap and hotspot information for a pointer icon, if it is not already loaded. - * Returns a pointer icon (not necessarily the same instance) with the information filled in. - * - * @param context The context. - * @return The loaded pointer icon. - * - * @throws IllegalArgumentException if context is null. - * @hide - */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) - public @NonNull PointerIcon load(@NonNull Context context) { - if (context == null) { - throw new IllegalArgumentException("context must not be null"); - } - - if (mSystemIconResourceId == 0 || mBitmap != null) { - return this; - } - - PointerIcon result = new PointerIcon(mType); - result.mSystemIconResourceId = mSystemIconResourceId; - result.loadResource(context, context.getResources(), mSystemIconResourceId); - return result; - } - /** @hide */ public int getType() { return mType; } - public static final @NonNull Parcelable.Creator<PointerIcon> CREATOR - = new Parcelable.Creator<PointerIcon>() { - public PointerIcon createFromParcel(Parcel in) { - int type = in.readInt(); - if (type == TYPE_NULL) { - return getNullIcon(); - } - - int systemIconResourceId = in.readInt(); - if (systemIconResourceId != 0) { - PointerIcon icon = new PointerIcon(type); - icon.mSystemIconResourceId = systemIconResourceId; - return icon; - } - - Bitmap bitmap = Bitmap.CREATOR.createFromParcel(in); - float hotSpotX = in.readFloat(); - float hotSpotY = in.readFloat(); - return PointerIcon.create(bitmap, hotSpotX, hotSpotY); - } + public static final @NonNull Parcelable.Creator<PointerIcon> CREATOR = + new Parcelable.Creator<>() { + @Override + public PointerIcon createFromParcel(Parcel in) { + final int type = in.readInt(); + if (type != TYPE_CUSTOM) { + return getSystemIcon(type); + } + final PointerIcon icon = + PointerIcon.create( + Bitmap.CREATOR.createFromParcel(in), + in.readFloat(), + in.readFloat()); + return icon; + } - public PointerIcon[] newArray(int size) { - return new PointerIcon[size]; - } - }; + @Override + public PointerIcon[] newArray(int size) { + return new PointerIcon[size]; + } + }; + @Override public int describeContents() { return 0; } + @Override public void writeToParcel(Parcel out, int flags) { out.writeInt(mType); + if (mType != TYPE_CUSTOM) { + // When parceling a non-custom icon type, do not write the icon bitmap into the parcel + // because it can be re-loaded from resources after un-parceling. + return; + } - if (mType != TYPE_NULL) { - out.writeInt(mSystemIconResourceId); - if (mSystemIconResourceId == 0) { - mBitmap.writeToParcel(out, flags); - out.writeFloat(mHotSpotX); - out.writeFloat(mHotSpotY); - } + if (!isLoaded()) { + throw new IllegalStateException("Custom icon should be loaded upon creation"); } + mBitmap.writeToParcel(out, flags); + out.writeFloat(mHotSpotX); + out.writeFloat(mHotSpotY); } @Override @@ -431,14 +375,13 @@ public final class PointerIcon implements Parcelable { } PointerIcon otherIcon = (PointerIcon) other; - if (mType != otherIcon.mType - || mSystemIconResourceId != otherIcon.mSystemIconResourceId) { + if (mType != otherIcon.mType) { return false; } - if (mSystemIconResourceId == 0 && (mBitmap != otherIcon.mBitmap + if (mBitmap != otherIcon.mBitmap || mHotSpotX != otherIcon.mHotSpotX - || mHotSpotY != otherIcon.mHotSpotY)) { + || mHotSpotY != otherIcon.mHotSpotY) { return false; } @@ -545,13 +488,13 @@ public final class PointerIcon implements Parcelable { mBitmap = bitmap; mHotSpotX = hotSpotX; mHotSpotY = hotSpotY; + assert isLoaded(); } @Override public String toString() { return "PointerIcon{type=" + typeToString(mType) - + ", hotspotX=" + mHotSpotX + ", hotspotY=" + mHotSpotY - + ", systemIconResourceId=" + mSystemIconResourceId + "}"; + + ", hotspotX=" + mHotSpotX + ", hotspotY=" + mHotSpotY + "}"; } private static void validateHotSpot(Bitmap bitmap, float hotSpotX, float hotSpotY) { @@ -623,31 +566,6 @@ public final class PointerIcon implements Parcelable { } /** - * Manage system icon cache handled by display lifecycle. - * @param context The context. - */ - private static void registerDisplayListener(@NonNull Context context) { - sDisplayListener = new DisplayManager.DisplayListener() { - @Override - public void onDisplayAdded(int displayId) { - } - - @Override - public void onDisplayRemoved(int displayId) { - gSystemIconsByDisplay.remove(displayId); - } - - @Override - public void onDisplayChanged(int displayId) { - gSystemIconsByDisplay.remove(displayId); - } - }; - - DisplayManager displayManager = context.getSystemService(DisplayManager.class); - displayManager.registerDisplayListener(sDisplayListener, null /* handler */); - } - - /** * Convert type constant to string. * @hide */ @@ -680,6 +598,7 @@ public final class PointerIcon implements Parcelable { case TYPE_ZOOM_OUT: return "ZOOM_OUT"; case TYPE_GRAB: return "GRAB"; case TYPE_GRABBING: return "GRABBING"; + case TYPE_HANDWRITING: return "HANDWRITING"; default: return Integer.toString(type); } } diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index c98d1d7ecaea..0f83d58d418d 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -5546,11 +5546,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, @FlaggedApi(FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY) public static final float REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE = -1; @FlaggedApi(FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY) - public static final float REQUESTED_FRAME_RATE_CATEGORY_LOW = -30; + public static final float REQUESTED_FRAME_RATE_CATEGORY_LOW = -2; @FlaggedApi(FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY) - public static final float REQUESTED_FRAME_RATE_CATEGORY_NORMAL = -60; + public static final float REQUESTED_FRAME_RATE_CATEGORY_NORMAL = -3; @FlaggedApi(FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY) - public static final float REQUESTED_FRAME_RATE_CATEGORY_HIGH = -120; + public static final float REQUESTED_FRAME_RATE_CATEGORY_HIGH = -4; /** * Simple constructor to use when creating a view from code. diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index e0bda9181380..3c36227eda0a 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -26,7 +26,6 @@ import static android.view.Display.INVALID_DISPLAY; import static android.view.InputDevice.SOURCE_CLASS_NONE; import static android.view.InsetsSource.ID_IME; import static android.view.Surface.FRAME_RATE_CATEGORY_HIGH; -import static android.view.Surface.FRAME_RATE_CATEGORY_HIGH_HINT; import static android.view.Surface.FRAME_RATE_CATEGORY_NO_PREFERENCE; import static android.view.View.PFLAG_DRAW_ANIMATION; import static android.view.View.SYSTEM_UI_FLAG_FULLSCREEN; @@ -1012,10 +1011,8 @@ public final class ViewRootImpl implements ViewParent, // Used to check if there were any view invalidations in // the previous time frame (FRAME_RATE_IDLENESS_REEVALUATE_TIME). private boolean mHasInvalidation = false; - // Used to check if it is in the frame rate boosting period. + // Used to check if it is in the touch boosting period. private boolean mIsFrameRateBoosting = false; - // Used to check if it is in touch boosting period. - private boolean mIsTouchBoosting = false; // Used to check if there is a message in the message queue // for idleness handling. private boolean mHasIdledMessage = false; @@ -6424,12 +6421,11 @@ public final class ViewRootImpl implements ViewParent, * Lower the frame rate after the boosting period (FRAME_RATE_TOUCH_BOOST_TIME). */ mIsFrameRateBoosting = false; - mIsTouchBoosting = false; setPreferredFrameRateCategory(Math.max(mPreferredFrameRateCategory, mLastPreferredFrameRateCategory)); break; case MSG_CHECK_INVALIDATION_IDLE: - if (!mHasInvalidation && !mIsFrameRateBoosting && !mIsTouchBoosting) { + if (!mHasInvalidation && !mIsFrameRateBoosting) { mPreferredFrameRateCategory = FRAME_RATE_CATEGORY_NO_PREFERENCE; setPreferredFrameRateCategory(mPreferredFrameRateCategory); mHasIdledMessage = false; @@ -7452,7 +7448,7 @@ public final class ViewRootImpl implements ViewParent, // For the variable refresh rate project if (handled && shouldTouchBoost(action, mWindowAttributes.type)) { // set the frame rate to the maximum value. - mIsTouchBoosting = true; + mIsFrameRateBoosting = true; setPreferredFrameRateCategory(mPreferredFrameRateCategory); } /** @@ -12204,16 +12200,8 @@ public final class ViewRootImpl implements ViewParent, return; } - int frameRateCategory = mIsTouchBoosting - ? FRAME_RATE_CATEGORY_HIGH_HINT : preferredFrameRateCategory; - - // FRAME_RATE_CATEGORY_HIGH has a higher precedence than FRAME_RATE_CATEGORY_HIGH_HINT - // For now, FRAME_RATE_CATEGORY_HIGH_HINT is used for boosting with user interaction. - // FRAME_RATE_CATEGORY_HIGH is for boosting without user interaction - // (e.g., Window Initialization). - if (mIsFrameRateBoosting || mInsetsAnimationRunning) { - frameRateCategory = FRAME_RATE_CATEGORY_HIGH; - } + int frameRateCategory = mIsFrameRateBoosting || mInsetsAnimationRunning + ? FRAME_RATE_CATEGORY_HIGH : preferredFrameRateCategory; try { if (mLastPreferredFrameRateCategory != frameRateCategory) { diff --git a/core/java/android/view/accessibility/flags/accessibility_flags.aconfig b/core/java/android/view/accessibility/flags/accessibility_flags.aconfig index efae57c9946c..a11ac7cb48ad 100644 --- a/core/java/android/view/accessibility/flags/accessibility_flags.aconfig +++ b/core/java/android/view/accessibility/flags/accessibility_flags.aconfig @@ -94,6 +94,13 @@ flag { } flag { + name: "skip_accessibility_warning_dialog_for_trusted_services" + namespace: "accessibility" + description: "Skips showing the accessibility warning dialog for trusted services." + bug: "303511250" +} + +flag { namespace: "accessibility" name: "update_always_on_a11y_service" description: "Updates the Always-On A11yService state when the user changes the enablement of the shortcut." diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java index d12eda35c745..14c53489ba3a 100644 --- a/core/java/android/webkit/WebSettings.java +++ b/core/java/android/webkit/WebSettings.java @@ -1203,11 +1203,7 @@ public abstract class WebSettings { * changes to this setting after that point. * * @param flag {@code true} if the WebView should use the database storage API - * @deprecated WebSQL is deprecated and this method will become a no-op on all - * Android versions once support is removed in Chromium. See - * https://developer.chrome.com/blog/deprecating-web-sql for more information. */ - @Deprecated public abstract void setDatabaseEnabled(boolean flag); /** @@ -1240,11 +1236,7 @@ public abstract class WebSettings { * * @return {@code true} if the database storage API is enabled * @see #setDatabaseEnabled - * @deprecated WebSQL is deprecated and this method will become a no-op on all - * Android versions once support is removed in Chromium. See - * https://developer.chrome.com/blog/deprecating-web-sql for more information. */ - @Deprecated public abstract boolean getDatabaseEnabled(); /** diff --git a/core/java/android/webkit/WebViewClient.java b/core/java/android/webkit/WebViewClient.java index 2dfeae3567e5..80aad60d8bc4 100644 --- a/core/java/android/webkit/WebViewClient.java +++ b/core/java/android/webkit/WebViewClient.java @@ -65,6 +65,14 @@ public class WebViewClient { * {@code true} causes the current WebView to abort loading the URL, while returning * {@code false} causes the WebView to continue loading the URL as usual. * + * <p>This callback is not called for all page navigations. In particular, this is not called + * for navigations which the app initiated with {@code loadUrl()}: this callback would not serve + * a purpose in this case, because the app already knows about the navigation. This callback + * lets the app know about navigations initiated by the web page (such as navigations initiated + * by JavaScript code), by the user (such as when the user taps on a link), or by an HTTP + * redirect (ex. if {@code loadUrl("foo.com")} redirects to {@code "bar.com"} because of HTTP + * 301). + * * <p class="note"><b>Note:</b> Do not call {@link WebView#loadUrl(String)} with the request's * URL and then return {@code true}. This unnecessarily cancels the current load and starts a * new load with the same URL. The correct way to continue loading a given URL is to simply diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 6da6a64dc042..e812f858b9fd 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -9589,6 +9589,23 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } break; + case KeyEvent.KEYCODE_ESCAPE: + if (com.android.text.flags.Flags.escapeClearsFocus() && event.hasNoModifiers()) { + if (mEditor != null && mEditor.getTextActionMode() != null) { + stopTextActionMode(); + return KEY_EVENT_HANDLED; + } + if (hasFocus()) { + clearFocus(); + InputMethodManager imm = getInputMethodManager(); + if (imm != null) { + imm.hideSoftInputFromView(this, 0); + } + return KEY_EVENT_HANDLED; + } + } + break; + case KeyEvent.KEYCODE_CUT: if (event.hasNoModifiers() && canCut()) { if (onTextContextMenuItem(ID_CUT)) { diff --git a/core/java/android/window/WindowTokenClient.java b/core/java/android/window/WindowTokenClient.java index c20b278f7eaa..7f5331b936e9 100644 --- a/core/java/android/window/WindowTokenClient.java +++ b/core/java/android/window/WindowTokenClient.java @@ -167,6 +167,11 @@ public class WindowTokenClient extends Binder { + ", reported config=" + currentConfig + ", updated config=" + newConfig); } + // Update display first. In case callers want to obtain display information( + // ex: DisplayMetrics) in #onConfigurationChanged callback. + if (displayChanged) { + context.updateDisplay(newDisplayId); + } if (shouldUpdateResources) { // TODO(ag/9789103): update resource manager logic to track non-activity tokens mResourcesManager.updateResourcesForActivity(this, newConfig, newDisplayId); @@ -195,9 +200,6 @@ public class WindowTokenClient extends Binder { } } } - if (displayChanged) { - context.updateDisplay(newDisplayId); - } } /** diff --git a/core/java/android/window/flags/responsible_apis.aconfig b/core/java/android/window/flags/responsible_apis.aconfig index f67eefa2281f..51890ecbecb5 100644 --- a/core/java/android/window/flags/responsible_apis.aconfig +++ b/core/java/android/window/flags/responsible_apis.aconfig @@ -36,13 +36,6 @@ flag { } flag { - name: "bal_return_correct_code_if_caller_is_persistent_system_process" - namespace: "responsible_apis" - description: "Split visibility check and return a better status code in case of system process." - bug: "171459802" -} - -flag { name: "bal_improve_real_caller_visibility_check" namespace: "responsible_apis" description: "Prevent a task to restart based on a visible window during task switch." diff --git a/core/java/com/android/internal/pm/pkg/component/ParsedProviderUtils.java b/core/java/com/android/internal/pm/pkg/component/ParsedProviderUtils.java index 5d82d0469d56..12aff1c6669f 100644 --- a/core/java/com/android/internal/pm/pkg/component/ParsedProviderUtils.java +++ b/core/java/com/android/internal/pm/pkg/component/ParsedProviderUtils.java @@ -29,6 +29,7 @@ import android.content.pm.parsing.result.ParseResult; import android.content.res.Resources; import android.content.res.TypedArray; import android.content.res.XmlResourceParser; +import android.multiuser.Flags; import android.os.Build; import android.os.PatternMatcher; import android.util.Slog; @@ -126,6 +127,10 @@ public class ParsedProviderUtils { .setFlags(provider.getFlags() | flag(ProviderInfo.FLAG_SINGLE_USER, R.styleable.AndroidManifestProvider_singleUser, sa)); + if (Flags.enableSystemUserOnlyForServicesAndProviders()) { + provider.setFlags(provider.getFlags() | flag(ProviderInfo.FLAG_SYSTEM_USER_ONLY, + R.styleable.AndroidManifestProvider_systemUserOnly, sa)); + } visibleToEphemeral = sa.getBoolean( R.styleable.AndroidManifestProvider_visibleToInstantApps, false); if (visibleToEphemeral) { diff --git a/core/java/com/android/internal/pm/pkg/component/ParsedServiceUtils.java b/core/java/com/android/internal/pm/pkg/component/ParsedServiceUtils.java index a1dd19a3bc90..4ac542f84226 100644 --- a/core/java/com/android/internal/pm/pkg/component/ParsedServiceUtils.java +++ b/core/java/com/android/internal/pm/pkg/component/ParsedServiceUtils.java @@ -29,6 +29,7 @@ import android.content.pm.parsing.result.ParseResult; import android.content.res.Resources; import android.content.res.TypedArray; import android.content.res.XmlResourceParser; +import android.multiuser.Flags; import android.os.Build; import com.android.internal.R; @@ -105,6 +106,11 @@ public class ParsedServiceUtils { | flag(ServiceInfo.FLAG_SINGLE_USER, R.styleable.AndroidManifestService_singleUser, sa))); + if (Flags.enableSystemUserOnlyForServicesAndProviders()) { + service.setFlags(service.getFlags() | flag(ServiceInfo.FLAG_SYSTEM_USER_ONLY, + R.styleable.AndroidManifestService_systemUserOnly, sa)); + } + visibleToEphemeral = sa.getBoolean( R.styleable.AndroidManifestService_visibleToInstantApps, false); if (visibleToEphemeral) { diff --git a/core/java/com/android/server/backup/AccountSyncSettingsBackupHelper.java b/core/java/com/android/server/backup/AccountSyncSettingsBackupHelper.java index ce9ab82614d5..2ff62251d786 100644 --- a/core/java/com/android/server/backup/AccountSyncSettingsBackupHelper.java +++ b/core/java/com/android/server/backup/AccountSyncSettingsBackupHelper.java @@ -21,6 +21,7 @@ import android.accounts.AccountManager; import android.app.backup.BackupDataInputStream; import android.app.backup.BackupDataOutput; import android.app.backup.BackupHelper; +import android.app.backup.BackupHelperWithLogger; import android.content.ContentResolver; import android.content.Context; import android.content.SyncAdapterType; @@ -56,7 +57,7 @@ import java.util.Set; * sync settings are backed up as a JSON object containing all the necessary information for * restoring the sync settings later. */ -public class AccountSyncSettingsBackupHelper implements BackupHelper { +public class AccountSyncSettingsBackupHelper extends BackupHelperWithLogger { private static final String TAG = "AccountSyncSettingsBackupHelper"; private static final boolean DEBUG = false; diff --git a/core/jni/Android.bp b/core/jni/Android.bp index c8fd246a255b..656cc3e2af71 100644 --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -188,8 +188,6 @@ cc_library_shared_for_libandroid_runtime { "android_os_SharedMemory.cpp", "android_os_storage_StorageManager.cpp", "android_os_UEventObserver.cpp", - "android_os_VintfObject.cpp", - "android_os_VintfRuntimeInfo.cpp", "android_os_incremental_IncrementalManager.cpp", "android_net_LocalSocketImpl.cpp", "android_service_DataLoaderService.cpp", @@ -280,6 +278,7 @@ cc_library_shared_for_libandroid_runtime { "libdmabufinfo", "libgif", "libgui_window_info_static", + "libkernelconfigs", "libseccomp_policy", "libgrallocusage", "libscrypt_static", @@ -350,7 +349,6 @@ cc_library_shared_for_libandroid_runtime { "libnativeloader_lazy", "libmemunreachable", "libhidlbase", - "libvintf", "libnativedisplay", "libnativewindow", "libdl", @@ -458,8 +456,25 @@ cc_library_shared_for_libandroid_runtime { // (e.g. gDefaultServiceManager) "libbinder", "libhidlbase", // libhwbinder is in here - "libvintf", ], }, }, } + +cc_library_shared { + name: "libvintf_jni", + + cpp_std: "gnu++20", + + srcs: [ + "android_os_VintfObject.cpp", + "android_os_VintfRuntimeInfo.cpp", + ], + + shared_libs: [ + "libbase", + "liblog", + "libnativehelper", + "libvintf", + ], +} diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index 7a16318f3276..aa63f4fa03d4 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -152,8 +152,6 @@ extern int register_android_os_MessageQueue(JNIEnv* env); extern int register_android_os_Parcel(JNIEnv* env); extern int register_android_os_PerformanceHintManager(JNIEnv* env); extern int register_android_os_SELinux(JNIEnv* env); -extern int register_android_os_VintfObject(JNIEnv *env); -extern int register_android_os_VintfRuntimeInfo(JNIEnv *env); extern int register_android_os_storage_StorageManager(JNIEnv* env); extern int register_android_os_SystemProperties(JNIEnv *env); extern int register_android_os_SystemClock(JNIEnv* env); @@ -1545,8 +1543,6 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_android_os_NativeHandle), REG_JNI(register_android_os_ServiceManager), REG_JNI(register_android_os_storage_StorageManager), - REG_JNI(register_android_os_VintfObject), - REG_JNI(register_android_os_VintfRuntimeInfo), REG_JNI(register_android_service_DataLoaderService), REG_JNI(register_android_view_DisplayEventReceiver), REG_JNI(register_android_view_Surface), diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp index de1ce4e29198..1504a00f972c 100644 --- a/core/jni/android_os_Debug.cpp +++ b/core/jni/android_os_Debug.cpp @@ -52,7 +52,7 @@ #include <memunreachable/memunreachable.h> #include <android-base/strings.h> #include "android_os_Debug.h" -#include <vintf/VintfObject.h> +#include <vintf/KernelConfigs.h> namespace android { @@ -1004,10 +1004,9 @@ static jboolean android_os_Debug_isVmapStack(JNIEnv *env, jobject clazz) } cfg_state = CONFIG_UNKNOWN; if (cfg_state == CONFIG_UNKNOWN) { - auto runtime_info = vintf::VintfObject::GetInstance()->getRuntimeInfo( - vintf::RuntimeInfo::FetchFlag::CONFIG_GZ); - CHECK(runtime_info != nullptr) << "Kernel configs cannot be fetched. b/151092221"; - const std::map<std::string, std::string>& configs = runtime_info->kernelConfigs(); + std::map<std::string, std::string> configs; + const status_t result = android::kernelconfigs::LoadKernelConfigs(&configs); + CHECK(result == OK) << "Kernel configs could not be fetched. b/151092221"; std::map<std::string, std::string>::const_iterator it = configs.find("CONFIG_VMAP_STACK"); cfg_state = (it != configs.end() && it->second == "y") ? CONFIG_SET : CONFIG_UNSET; } diff --git a/core/jni/android_os_HwBinder.cpp b/core/jni/android_os_HwBinder.cpp index 477bd096b11a..734b5f497e2e 100644 --- a/core/jni/android_os_HwBinder.cpp +++ b/core/jni/android_os_HwBinder.cpp @@ -39,7 +39,6 @@ #include <hwbinder/ProcessState.h> #include <nativehelper/ScopedLocalRef.h> #include <nativehelper/ScopedUtfChars.h> -#include <vintf/parse_string.h> #include <utils/misc.h> #include "core_jni_helpers.h" diff --git a/core/jni/android_os_VintfObject.cpp b/core/jni/android_os_VintfObject.cpp index a5b2f65eafc7..ce4a33735c6d 100644 --- a/core/jni/android_os_VintfObject.cpp +++ b/core/jni/android_os_VintfObject.cpp @@ -17,16 +17,14 @@ #define LOG_TAG "VintfObject" //#define LOG_NDEBUG 0 #include <android-base/logging.h> - -#include <vector> -#include <string> - -#include <nativehelper/JNIHelp.h> #include <vintf/VintfObject.h> #include <vintf/parse_string.h> #include <vintf/parse_xml.h> -#include "core_jni_helpers.h" +#include <vector> +#include <string> + +#include "jni_wrappers.h" static jclass gString; static jclass gHashMapClazz; @@ -94,7 +92,7 @@ static jobjectArray android_os_VintfObject_report(JNIEnv* env, jclass) return toJavaStringArray(env, cStrings); } -static jint android_os_VintfObject_verifyBuildAtBoot(JNIEnv* env, jclass) { +static jint android_os_VintfObject_verifyBuildAtBoot(JNIEnv*, jclass) { std::string error; // Use temporary VintfObject, not the shared instance, to release memory // after check. @@ -204,4 +202,23 @@ int register_android_os_VintfObject(JNIEnv* env) NELEM(gVintfObjectMethods)); } -}; +extern int register_android_os_VintfRuntimeInfo(JNIEnv* env); + +} // namespace android + +jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) { + JNIEnv* env = NULL; + if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6)) { + return JNI_ERR; + } + + if (android::register_android_os_VintfObject(env) < 0) { + return JNI_ERR; + } + + if (android::register_android_os_VintfRuntimeInfo(env) < 0) { + return JNI_ERR; + } + + return JNI_VERSION_1_6; +} diff --git a/core/jni/android_os_VintfRuntimeInfo.cpp b/core/jni/android_os_VintfRuntimeInfo.cpp index b0271b9e92af..7c2f58829446 100644 --- a/core/jni/android_os_VintfRuntimeInfo.cpp +++ b/core/jni/android_os_VintfRuntimeInfo.cpp @@ -17,23 +17,22 @@ #define LOG_TAG "VintfRuntimeInfo" //#define LOG_NDEBUG 0 -#include <nativehelper/JNIHelp.h> #include <vintf/VintfObject.h> #include <vintf/parse_string.h> #include <vintf/parse_xml.h> -#include "core_jni_helpers.h" +#include "jni_wrappers.h" namespace android { using vintf::RuntimeInfo; using vintf::VintfObject; -#define MAP_STRING_METHOD(javaMethod, cppString, flags) \ - static jstring android_os_VintfRuntimeInfo_##javaMethod(JNIEnv* env, jclass clazz) { \ - std::shared_ptr<const RuntimeInfo> info = VintfObject::GetRuntimeInfo(flags); \ - if (info == nullptr) return nullptr; \ - return env->NewStringUTF((cppString).c_str()); \ +#define MAP_STRING_METHOD(javaMethod, cppString, flags) \ + static jstring android_os_VintfRuntimeInfo_##javaMethod(JNIEnv* env, jclass) { \ + std::shared_ptr<const RuntimeInfo> info = VintfObject::GetRuntimeInfo(flags); \ + if (info == nullptr) return nullptr; \ + return env->NewStringUTF((cppString).c_str()); \ } MAP_STRING_METHOD(getCpuInfo, info->cpuInfo(), RuntimeInfo::FetchFlag::CPU_INFO); @@ -49,9 +48,7 @@ MAP_STRING_METHOD(getBootAvbVersion, vintf::to_string(info->bootAvbVersion()), MAP_STRING_METHOD(getBootVbmetaAvbVersion, vintf::to_string(info->bootVbmetaAvbVersion()), RuntimeInfo::FetchFlag::AVB); - -static jlong android_os_VintfRuntimeInfo_getKernelSepolicyVersion(JNIEnv *env, jclass clazz) -{ +static jlong android_os_VintfRuntimeInfo_getKernelSepolicyVersion(JNIEnv*, jclass) { std::shared_ptr<const RuntimeInfo> info = VintfObject::GetRuntimeInfo(RuntimeInfo::FetchFlag::POLICYVERS); if (info == nullptr) return 0; diff --git a/core/jni/android_view_PointerIcon.cpp b/core/jni/android_view_PointerIcon.cpp index d57ec1528c69..c6a3b52d9397 100644 --- a/core/jni/android_view_PointerIcon.cpp +++ b/core/jni/android_view_PointerIcon.cpp @@ -18,12 +18,12 @@ #include "android_view_PointerIcon.h" +#include <android-base/logging.h> #include <android/graphics/bitmap.h> #include <android_runtime/AndroidRuntime.h> #include <android_runtime/Log.h> #include <nativehelper/JNIHelp.h> #include <nativehelper/ScopedLocalRef.h> -#include <utils/Log.h> #include "core_jni_helpers.h" @@ -37,90 +37,41 @@ static struct { jfieldID mHotSpotY; jfieldID mBitmapFrames; jfieldID mDurationPerFrame; - jmethodID getSystemIcon; - jmethodID load; } gPointerIconClassInfo; // --- Global Functions --- -jobject android_view_PointerIcon_getSystemIcon(JNIEnv* env, jobject contextObj, - PointerIconStyle style) { - jobject pointerIconObj = env->CallStaticObjectMethod(gPointerIconClassInfo.clazz, - gPointerIconClassInfo.getSystemIcon, contextObj, style); - if (env->ExceptionCheck()) { - ALOGW("An exception occurred while getting a pointer icon with style %d.", style); - LOGW_EX(env); - env->ExceptionClear(); - return NULL; - } - return pointerIconObj; -} - -status_t android_view_PointerIcon_load(JNIEnv* env, jobject pointerIconObj, jobject contextObj, - PointerIcon* outPointerIcon) { - outPointerIcon->reset(); - +PointerIcon android_view_PointerIcon_toNative(JNIEnv* env, jobject pointerIconObj) { if (!pointerIconObj) { - return OK; + LOG(FATAL) << __func__ << ": pointerIconObj is null"; } - - ScopedLocalRef<jobject> loadedPointerIconObj(env, env->CallObjectMethod(pointerIconObj, - gPointerIconClassInfo.load, contextObj)); - if (env->ExceptionCheck() || !loadedPointerIconObj.get()) { - ALOGW("An exception occurred while loading a pointer icon."); - LOGW_EX(env); - env->ExceptionClear(); - return UNKNOWN_ERROR; - } - return android_view_PointerIcon_getLoadedIcon(env, loadedPointerIconObj.get(), outPointerIcon); -} - -status_t android_view_PointerIcon_getLoadedIcon(JNIEnv* env, jobject pointerIconObj, - PointerIcon* outPointerIcon) { - if (!pointerIconObj) { - return BAD_VALUE; - } - outPointerIcon->style = static_cast<PointerIconStyle>( + PointerIcon icon; + icon.style = static_cast<PointerIconStyle>( env->GetIntField(pointerIconObj, gPointerIconClassInfo.mType)); - outPointerIcon->hotSpotX = env->GetFloatField(pointerIconObj, gPointerIconClassInfo.mHotSpotX); - outPointerIcon->hotSpotY = env->GetFloatField(pointerIconObj, gPointerIconClassInfo.mHotSpotY); + icon.hotSpotX = env->GetFloatField(pointerIconObj, gPointerIconClassInfo.mHotSpotX); + icon.hotSpotY = env->GetFloatField(pointerIconObj, gPointerIconClassInfo.mHotSpotY); ScopedLocalRef<jobject> bitmapObj( env, env->GetObjectField(pointerIconObj, gPointerIconClassInfo.mBitmap)); if (bitmapObj.get()) { - outPointerIcon->bitmap = graphics::Bitmap(env, bitmapObj.get()); + icon.bitmap = graphics::Bitmap(env, bitmapObj.get()); } ScopedLocalRef<jobjectArray> bitmapFramesObj(env, reinterpret_cast<jobjectArray>( env->GetObjectField(pointerIconObj, gPointerIconClassInfo.mBitmapFrames))); if (bitmapFramesObj.get()) { - outPointerIcon->durationPerFrame = env->GetIntField( - pointerIconObj, gPointerIconClassInfo.mDurationPerFrame); + icon.durationPerFrame = + env->GetIntField(pointerIconObj, gPointerIconClassInfo.mDurationPerFrame); jsize size = env->GetArrayLength(bitmapFramesObj.get()); - outPointerIcon->bitmapFrames.resize(size); + icon.bitmapFrames.resize(size); for (jsize i = 0; i < size; ++i) { ScopedLocalRef<jobject> bitmapObj(env, env->GetObjectArrayElement(bitmapFramesObj.get(), i)); - outPointerIcon->bitmapFrames[i] = graphics::Bitmap(env, bitmapObj.get()); + icon.bitmapFrames[i] = graphics::Bitmap(env, bitmapObj.get()); } } - return OK; -} - -status_t android_view_PointerIcon_loadSystemIcon(JNIEnv* env, jobject contextObj, - PointerIconStyle style, - PointerIcon* outPointerIcon) { - jobject pointerIconObj = android_view_PointerIcon_getSystemIcon(env, contextObj, style); - if (!pointerIconObj) { - outPointerIcon->reset(); - return UNKNOWN_ERROR; - } - - status_t status = android_view_PointerIcon_load(env, pointerIconObj, - contextObj, outPointerIcon); - env->DeleteLocalRef(pointerIconObj); - return status; + return icon; } // --- JNI Registration --- @@ -147,12 +98,6 @@ int register_android_view_PointerIcon(JNIEnv* env) { gPointerIconClassInfo.mDurationPerFrame = GetFieldIDOrDie(env, gPointerIconClassInfo.clazz, "mDurationPerFrame", "I"); - gPointerIconClassInfo.getSystemIcon = GetStaticMethodIDOrDie(env, gPointerIconClassInfo.clazz, - "getSystemIcon", "(Landroid/content/Context;I)Landroid/view/PointerIcon;"); - - gPointerIconClassInfo.load = GetMethodIDOrDie(env, gPointerIconClassInfo.clazz, - "load", "(Landroid/content/Context;)Landroid/view/PointerIcon;"); - return 0; } diff --git a/core/jni/android_view_PointerIcon.h b/core/jni/android_view_PointerIcon.h index f3eaad3d0a9f..ee446fb92a4f 100644 --- a/core/jni/android_view_PointerIcon.h +++ b/core/jni/android_view_PointerIcon.h @@ -52,24 +52,12 @@ struct PointerIcon { } }; -/* Gets a system pointer icon with the specified style. */ -extern jobject android_view_PointerIcon_getSystemIcon(JNIEnv* env, jobject contextObj, - PointerIconStyle style); - -/* Loads the bitmap associated with a pointer icon. - * If pointerIconObj is NULL, returns OK and a pointer icon with POINTER_ICON_STYLE_NULL. */ -extern status_t android_view_PointerIcon_load(JNIEnv* env, jobject pointerIconObj, - jobject contextObj, PointerIcon* outPointerIcon); - -/* Obtain the data of pointerIconObj and put to outPointerIcon. */ -extern status_t android_view_PointerIcon_getLoadedIcon(JNIEnv* env, jobject pointerIconObj, - PointerIcon* outPointerIcon); - -/* Loads the bitmap associated with a pointer icon by style. - * If pointerIconObj is NULL, returns OK and a pointer icon with POINTER_ICON_STYLE_NULL. */ -extern status_t android_view_PointerIcon_loadSystemIcon(JNIEnv* env, jobject contextObj, - PointerIconStyle style, - PointerIcon* outPointerIcon); +/* + * Obtain the data of the Java pointerIconObj into a native PointerIcon. + * + * The pointerIconObj must not be null. + */ +PointerIcon android_view_PointerIcon_toNative(JNIEnv* env, jobject pointerIconObj); } // namespace android diff --git a/core/jni/core_jni_helpers.h b/core/jni/core_jni_helpers.h index 210dc895d674..769fa723c96e 100644 --- a/core/jni/core_jni_helpers.h +++ b/core/jni/core_jni_helpers.h @@ -22,6 +22,8 @@ #include <nativehelper/scoped_utf_chars.h> #include <android_runtime/AndroidRuntime.h> +#include "jni_wrappers.h" + // Host targets (layoutlib) do not differentiate between regular and critical native methods, // and they need all the JNI methods to have JNIEnv* and jclass/jobject as their first two arguments. // The following macro allows to have those arguments when compiling for host while omitting them when @@ -36,60 +38,6 @@ namespace android { -// Defines some helpful functions. - -static inline jclass FindClassOrDie(JNIEnv* env, const char* class_name) { - jclass clazz = env->FindClass(class_name); - LOG_ALWAYS_FATAL_IF(clazz == NULL, "Unable to find class %s", class_name); - return clazz; -} - -static inline jfieldID GetFieldIDOrDie(JNIEnv* env, jclass clazz, const char* field_name, - const char* field_signature) { - jfieldID res = env->GetFieldID(clazz, field_name, field_signature); - LOG_ALWAYS_FATAL_IF(res == NULL, "Unable to find field %s with signature %s", field_name, - field_signature); - return res; -} - -static inline jmethodID GetMethodIDOrDie(JNIEnv* env, jclass clazz, const char* method_name, - const char* method_signature) { - jmethodID res = env->GetMethodID(clazz, method_name, method_signature); - LOG_ALWAYS_FATAL_IF(res == NULL, "Unable to find method %s with signature %s", method_name, - method_signature); - return res; -} - -static inline jfieldID GetStaticFieldIDOrDie(JNIEnv* env, jclass clazz, const char* field_name, - const char* field_signature) { - jfieldID res = env->GetStaticFieldID(clazz, field_name, field_signature); - LOG_ALWAYS_FATAL_IF(res == NULL, "Unable to find static field %s with signature %s", field_name, - field_signature); - return res; -} - -static inline jmethodID GetStaticMethodIDOrDie(JNIEnv* env, jclass clazz, const char* method_name, - const char* method_signature) { - jmethodID res = env->GetStaticMethodID(clazz, method_name, method_signature); - LOG_ALWAYS_FATAL_IF(res == NULL, "Unable to find static method %s with signature %s", - method_name, method_signature); - return res; -} - -template <typename T> -static inline T MakeGlobalRefOrDie(JNIEnv* env, T in) { - jobject res = env->NewGlobalRef(in); - LOG_ALWAYS_FATAL_IF(res == NULL, "Unable to create global reference."); - return static_cast<T>(res); -} - -static inline int RegisterMethodsOrDie(JNIEnv* env, const char* className, - const JNINativeMethod* gMethods, int numMethods) { - int res = AndroidRuntime::registerNativeMethods(env, className, gMethods, numMethods); - LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register native methods."); - return res; -} - /** * Returns the result of invoking java.lang.ref.Reference.get() on a Reference object. */ diff --git a/core/jni/jni_wrappers.h b/core/jni/jni_wrappers.h new file mode 100644 index 000000000000..3b29e305e410 --- /dev/null +++ b/core/jni/jni_wrappers.h @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +// JNI wrappers for better logging + +#include <jni.h> +#include <log/log.h> +#include <nativehelper/JNIHelp.h> + +namespace android { + +static inline jclass FindClassOrDie(JNIEnv* env, const char* class_name) { + jclass clazz = env->FindClass(class_name); + LOG_ALWAYS_FATAL_IF(clazz == NULL, "Unable to find class %s", class_name); + return clazz; +} + +static inline jfieldID GetFieldIDOrDie(JNIEnv* env, jclass clazz, const char* field_name, + const char* field_signature) { + jfieldID res = env->GetFieldID(clazz, field_name, field_signature); + LOG_ALWAYS_FATAL_IF(res == NULL, "Unable to find field %s with signature %s", field_name, + field_signature); + return res; +} + +static inline jmethodID GetMethodIDOrDie(JNIEnv* env, jclass clazz, const char* method_name, + const char* method_signature) { + jmethodID res = env->GetMethodID(clazz, method_name, method_signature); + LOG_ALWAYS_FATAL_IF(res == NULL, "Unable to find method %s with signature %s", method_name, + method_signature); + return res; +} + +static inline jfieldID GetStaticFieldIDOrDie(JNIEnv* env, jclass clazz, const char* field_name, + const char* field_signature) { + jfieldID res = env->GetStaticFieldID(clazz, field_name, field_signature); + LOG_ALWAYS_FATAL_IF(res == NULL, "Unable to find static field %s with signature %s", field_name, + field_signature); + return res; +} + +static inline jmethodID GetStaticMethodIDOrDie(JNIEnv* env, jclass clazz, const char* method_name, + const char* method_signature) { + jmethodID res = env->GetStaticMethodID(clazz, method_name, method_signature); + LOG_ALWAYS_FATAL_IF(res == NULL, "Unable to find static method %s with signature %s", + method_name, method_signature); + return res; +} + +template <typename T> +static inline T MakeGlobalRefOrDie(JNIEnv* env, T in) { + jobject res = env->NewGlobalRef(in); + LOG_ALWAYS_FATAL_IF(res == NULL, "Unable to create global reference."); + return static_cast<T>(res); +} + +static inline int RegisterMethodsOrDie(JNIEnv* env, const char* className, + const JNINativeMethod* gMethods, int numMethods) { + int res = jniRegisterNativeMethods(env, className, gMethods, numMethods); + LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register native methods."); + return res; +} + +} // namespace android diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index a3d5cf6e3ab5..f9731d4b907c 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -2961,7 +2961,7 @@ <p>Protection level: signature @SystemApi @hide - @FlaggedApi("com.android.internal.telephony.flags.ap_domain_selection_enabled") + @FlaggedApi("com.android.internal.telephony.flags.use_oem_domain_selection_service") --> <permission android:name="android.permission.BIND_DOMAIN_SELECTION_SERVICE" android:protectionLevel="signature" /> @@ -3569,6 +3569,13 @@ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_NEARBY_COMMUNICATION" android:protectionLevel="internal|role" /> + <!-- Allows an application to set policy related to <a + href="https://www.threadgroup.org">Thread</a> network. + @FlaggedApi("com.android.net.thread.flags.thread_user_restriction_enabled") + --> + <permission android:name="android.permission.MANAGE_DEVICE_POLICY_THREAD_NETWORK" + android:protectionLevel="internal|role" /> + <!-- Allows an application to set policy related to windows. <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is required to call APIs protected by this permission on users different to the calling user. @@ -4961,7 +4968,7 @@ <p>Protection level: signature --> <permission android:name="android.permission.BIND_NFC_SERVICE" - android:protectionLevel="signature" /> + android:protectionLevel="signature|module" /> <!-- Must be required by a {@link android.service.quickaccesswallet.QuickAccessWalletService} to ensure that only the system can bind to it. @@ -5695,6 +5702,7 @@ @hide --> <permission android:name="android.permission.MANAGE_ROLE_HOLDERS" android:protectionLevel="signature|installer|module" /> + <uses-permission android:name="android.permission.MANAGE_ROLE_HOLDERS" /> <!-- @SystemApi Allows an application to manage the holders of roles associated with default applications. @@ -5729,6 +5737,14 @@ android:description="@string/permdesc_observeCompanionDevicePresence" android:protectionLevel="normal" /> + <!-- Allows an application to subscribe to notifications about the nearby devices' presence + status change base on the UUIDs. + <p>Not for use by third-party applications.</p> + @FlaggedApi("android.companion.flags.device_presence") + --> + <permission android:name="android.permission.REQUEST_OBSERVE_DEVICE_UUID_PRESENCE" + android:protectionLevel="signature|privileged" /> + <!-- Allows an application to deliver companion messages to system --> <permission android:name="android.permission.DELIVER_COMPANION_MESSAGES" diff --git a/core/res/res/drawable/autofill_half_sheet_divider.xml b/core/res/res/drawable/autofill_half_sheet_divider.xml new file mode 100644 index 000000000000..1a96c7dc263e --- /dev/null +++ b/core/res/res/drawable/autofill_half_sheet_divider.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- Copied from //frameworks/base/core/res/res/drawable/list_divider_material.xml. --> +<shape xmlns:android="http://schemas.android.com/apk/res/android" + android:tint="@color/foreground_material_light"> + <solid android:color="#1f000000" /> + <size + android:height="1dp" + android:width="1dp"/> +</shape>
\ No newline at end of file diff --git a/core/res/res/layout/autofill_save.xml b/core/res/res/layout/autofill_save.xml index 27f8138ac5e3..ddedca2865c4 100644 --- a/core/res/res/layout/autofill_save.xml +++ b/core/res/res/layout/autofill_save.xml @@ -31,11 +31,11 @@ android:gravity="center_horizontal" android:orientation="vertical"> <ScrollView + android:id="@+id/autofill_sheet_scroll_view" android:layout_width="fill_parent" android:layout_height="0dp" android:fillViewport="true" - android:layout_weight="1" - android:layout_marginBottom="8dp"> + android:layout_weight="1"> <LinearLayout android:layout_marginStart="@dimen/autofill_save_outer_margin" android:layout_marginEnd="@dimen/autofill_save_outer_margin" @@ -66,16 +66,25 @@ android:layout_height="wrap_content" android:minHeight="0dp" android:visibility="gone"/> - + <View + android:id="@+id/autofill_sheet_scroll_view_space" + android:layout_width="match_parent" + android:layout_height="16dp"/> </LinearLayout> </ScrollView> + <View + android:id="@+id/autofill_sheet_divider" + android:layout_width="match_parent" + android:layout_height="1dp" + style="@style/AutofillHalfSheetDivider" /> + <com.android.internal.widget.ButtonBarLayout android:layout_width="match_parent" android:layout_height="48dp" android:layout_gravity="end" android:clipToPadding="false" - android:layout_marginTop="16dp" + android:layout_marginTop="8dp" android:layout_marginBottom="8dp" android:theme="@style/Theme.DeviceDefault.AutofillHalfScreenDialogButton" android:orientation="horizontal" diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml index b60bd6348c00..38d2a255f30a 100644 --- a/core/res/res/values-af/strings.xml +++ b/core/res/res/values-af/strings.xml @@ -434,10 +434,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Laat die app toe om die voorgronddienstipe “stelselvrystelling” te gebruik"</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"gebruik voorgronddienstipe “lêerbestuur”"</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"Laat die app toe om die voorgronddienstipe “lêerbestuur” te gebruik"</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"gebruik voorgronddienstipe “mediaverwerking”"</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"Laat die app toe om die voorgronddienstipe “mediaverwerking” te gebruik"</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"gebruik voorgronddienstipe “spesiale gebruik”"</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Laat die app toe om die voorgronddienstipe “spesiale gebruik” te gebruik"</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"meet programberging-ruimte"</string> @@ -636,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Gebruik skermslot"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Voer jou skermslot in om voort te gaan"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Druk ferm op die sensor"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Vingerafdruk word nie herken nie. Probeer weer."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Maak vingerafdruksensor skoon en probeer weer"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Maak sensor skoon en probeer weer"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Druk ferm op sensor"</string> @@ -701,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"Kan nie jou gesig sien nie. Hou jou foon op oogvlak."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Te veel beweging. Hou foon stil."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Skryf jou gesig asseblief weer in."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"Gesig word nie herken nie. Probeer weer."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Verander die posisie van jou kop effens"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Kyk meer reguit na jou foon"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Kyk meer reguit na jou foon"</string> diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml index 5a6ef3c7f7dd..47d2da09b8ae 100644 --- a/core/res/res/values-am/strings.xml +++ b/core/res/res/values-am/strings.xml @@ -434,10 +434,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"መተግበሪያው የፊት አገልግሎትን በ«systemExempted» ዓይነት እንዲጠቀም ይፈቅዳል"</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"የፊት አገልግሎትን በ«fileManagement» ዓይነት ማስሄድ"</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"መተግበሪያው የፊት አገልግሎቶችን በ«fileManagement» ዓይነት እንዲጠቀም ያስችላል"</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"የፊት ለፊት አገልግሎትን በ«mediaProcessing» ዓይነት ማስሄድ"</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"መተግበሪያው የፊት ለፊት አገልግሎቶችን በ«mediaProcessing» ዓይነት እንዲጠቀም ያስችላል"</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"የፊት አገልግሎትን በ«specialUse» ዓይነት ማስሄድ"</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"መተግበሪያው የፊት አገልግሎትን በ«specialUse» ዓይነት እንዲጠቀም ይፈቅዳል"</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"የመተግበሪያ ማከማቻ ቦታ ለካ"</string> @@ -636,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"የማያ ገፅ መቆለፊን ይጠቀሙ"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"ለመቀጠል የማያ ገፅ ቁልፍዎን ያስገቡ"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"ዳሳሹን በደንብ ይጫኑት"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"የጣት አሻራ አልታወቀም። እንደገና ይሞክሩ።"</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"የጣት አሻራ ዳሳሽን ያጽዱ እና እንደገና ይሞክሩ"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"ዳሳሹን ያጽዱ እና እንደገና ይሞክሩ"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"ዳሳሹን ጠበቅ አድርገው ይጫኑት"</string> @@ -701,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"የእርስዎን መልክ ማየት አይችልም። ስልክዎን በዓይን ትክክል ይያዙ።"</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"ከልክ በላይ ብዙ እንቅስቃሴ። ስልኩን ቀጥ አድርገው ይያዙት።"</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"እባክዎ ፊትዎን እንደገና ያስመዝግቡ"</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"ፊቱ አልታወቀም። እንደገና ይሞክሩ።"</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"የጭንቅላትዎን ቦታ በትንሹ ይለዋውጡ"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"ስልክዎን ይበልጥ በቀጥታ ይመልከቱ"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"ስልክዎን ይበልጥ በቀጥታ ይመልከቱ"</string> diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml index 136ad53359da..4d6b92f4db5b 100644 --- a/core/res/res/values-ar/strings.xml +++ b/core/res/res/values-ar/strings.xml @@ -438,10 +438,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"يسمح هذا الإذن للتطبيق بالاستفادة من الخدمات التي تعمل في المقدّمة ذات النوع \"systemExempted\"."</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"تشغيل الخدمة التي تعمل في المقدّمة ذات النوع \"fileManagement\""</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"يسمح هذا الإذن للتطبيق بالاستفادة من الخدمات التي تعمل في المقدّمة ذات النوع \"fileManagement\""</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"تشغيل الخدمة التي تعمل في المقدّمة ذات النوع \"mediaProcessing\""</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"يسمح هذا الإذن للتطبيق بالاستفادة من الخدمات التي تعمل في المقدّمة ذات النوع \"mediaProcessing\"."</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"تشغيل الخدمة التي تعمل في المقدّمة ذات النوع \"specialUse\""</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"يسمح هذا الإذن للتطبيق بالاستفادة من الخدمات التي تعمل في المقدّمة ذات النوع \"specialUse\"."</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"قياس مساحة تخزين التطبيق"</string> @@ -640,8 +638,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"استخدام قفل الشاشة"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"أدخِل قفل الشاشة للمتابعة"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"اضغط بقوة على أداة الاستشعار"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"لم يتم التعرّف على بصمة الإصبع. يُرجى إعادة المحاولة."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"يُرجى تنظيف مستشعر بصمات الإصبع ثم إعادة المحاولة."</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"تنظيف المستشعر ثم إعادة المحاولة"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"اضغط بقوة على أداة الاستشعار"</string> @@ -705,8 +702,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"ارفع هاتفك إلى مستوى العينَين لأنّه تتعذّر رؤية وجهك"</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"حركة أكثر من اللازم. يُرجى حمل الهاتف بثبات."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"يُرجى إعادة تسجيل وجهك."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"يتعذّر التعرّف على الوجه. يُرجى إعادة المحاولة."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"غيِّر موضع رأسك قليلاً."</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"يُرجى النظر إلى هاتفك مباشرةً"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"يُرجى النظر إلى هاتفك مباشرةً"</string> diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml index fa9e2d782ef8..94d355f4b297 100644 --- a/core/res/res/values-as/strings.xml +++ b/core/res/res/values-as/strings.xml @@ -434,10 +434,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"এপ্টোক \"systemExempted\" সম্পৰ্কীয় অগ্ৰভূমি সেৱাসমূহ ব্যৱহাৰ কৰিবলৈ অনুমতি দিয়ে"</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"\"fileManagement\" সম্পৰ্কীয় অগ্ৰভূমি সেৱাসমূহ চলাওক"</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"এপ্টোক \"fileManagement\" সম্পৰ্কীয় অগ্ৰভূমি সেৱাসমূহ ব্যৱহাৰ কৰিবলৈ অনুমতি দিয়ে"</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"\"mediaProcessing\" সম্পৰ্কীয় অগ্ৰভূমি সেৱাসমূহ চলাওক"</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"এপ্টোক \"mediaProcessing\" সম্পৰ্কীয় অগ্ৰভূমি সেৱাসমূহ ব্যৱহাৰ কৰিবলৈ অনুমতি দিয়ে"</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"\"specialUse\" সম্পৰ্কীয় অগ্ৰভূমি সেৱাসমূহ চলাওক"</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"এপ্টোক \"specialUse\" সম্পৰ্কীয় অগ্ৰভূমি সেৱাসমূহ ব্যৱহাৰ কৰিবলৈ অনুমতি দিয়ে"</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"এপৰ ষ্ট’ৰেজৰ খালী ঠাই হিচাপ কৰক"</string> @@ -636,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"স্ক্ৰীন ল\'ক ব্যৱহাৰ কৰক"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"অব্যাহত ৰাখিবলৈ আপোনাৰ স্ক্ৰীন লক দিয়ক"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"ছেন্সৰটোত ভালকৈ টিপক"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"ফিংগাৰপ্ৰিণ্ট চিনাক্ত কৰিব পৰা নাই। পুনৰ চেষ্টা কৰক।"</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"ফিংগাৰপ্ৰিণ্ট ছেন্সৰটো মচি পুনৰ চেষ্টা কৰক"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"ছেন্সৰটো মচি পুনৰ চেষ্টা কৰক"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"ছেন্সৰটোত ভালকৈ টিপক"</string> @@ -701,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"আপোনাৰ মুখাৱয়ব দেখা নাই। আপোনাৰ ফ’নটো চকুৰ স্তৰত ধৰি ৰাখক।"</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"বেছি লৰচৰ কৰি আছে। ফ’নটো স্থিৰকৈ ধৰক।"</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"আপোনাৰ মুখমণ্ডল পুনৰ পঞ্জীয়ন কৰক।"</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"মুখাৱয়ব চিনাক্ত কৰিব পৰা নাই। পুনৰ চেষ্টা কৰক।"</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"আপোনাৰ মূৰটোৰ স্থান সামান্য সলনি কৰক"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"আপোনাৰ ফ’নটোলৈ আৰু পোনপটীয়াকৈ চাওক"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"আপোনাৰ ফ’নটোলৈ আৰু পোনপটীয়াকৈ চাওক"</string> diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml index d4df38e96928..633f6de88a70 100644 --- a/core/res/res/values-az/strings.xml +++ b/core/res/res/values-az/strings.xml @@ -434,10 +434,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Tətbiqə \"systemExempted\" növü olan ön fon xidmətlərini işlətmək icazəsi verir"</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"\"fileManagement\" növü olan ön fon xidmətlərini işə salmaq"</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"Tətbiqə \"fileManagement\" növü olan ön fon xidmətlərini işlətmək icazəsi verir"</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"\"mediaProcessing\" növü ilə ön fon xidmətini işə salmaq"</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"Tətbiqə \"mediaProcessing\" növü ilə ön fon xidmətlərindən istifadə icazəsi verir"</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"\"specialUse\" növü olan ön fon xidmətləri işlətmək"</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Tətbiqə \"specialUse\" növü olan ön fon xidmətlərini işlətmək icazəsi verir"</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"tətbiq saxlama yaddaşını ölçmək"</string> @@ -636,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Ekran kilidindən istifadə edin"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Davam etmək üçün ekran kilidinizi daxil edin"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Sensora basıb saxlayın"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Barmaq izi tanınmadı. Yenidən cəhd edin."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Barmaq izi sensorunu silib yenidən cəhd edin"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Sensoru silib yenidən cəhd edin"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Sensora basıb saxlayın"</string> @@ -701,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"Üzünüz görünmür. Telefonunuzu göz səviyyəsində saxlayın."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Cihaz stabil deyil. Telefonu tərpətməyin."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Üzünüzü yenidən qeydiyyatdan keçirin."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"Üz tanınmadı. Yenidən cəhd edin."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Başınızın yerini bir az dəyişdirin"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Telefonunuza düz baxın"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Telefonunuza düz baxın"</string> diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml index e19a0b2886a0..83879846e459 100644 --- a/core/res/res/values-b+sr+Latn/strings.xml +++ b/core/res/res/values-b+sr+Latn/strings.xml @@ -435,10 +435,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Dozvoljava aplikaciji da koristi usluge u prvom planu koje pripadaju tipu „systemExempted“"</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"pokretanje usluge u prvom planu koja pripada tipu „fileManagement“"</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"Dozvoljava aplikaciji da koristi usluge u prvom planu koje pripadaju tipu „fileManagement“"</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"pokretanje usluge u prvom planu koja pripada tipu „mediaProcessing“"</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"Dozvoljava aplikaciji da koristi usluge u prvom planu koje pripadaju tipu „mediaProcessing“"</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"pokretanje usluge u prvom planu koja pripada tipu „specialUse“"</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Dozvoljava aplikaciji da koristi usluge u prvom planu koje pripadaju tipu „specialUse“"</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"merenje memorijskog prostora u aplikaciji"</string> @@ -637,8 +635,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Koristite zaključavanje ekrana"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Upotrebite zaključavanje ekrana da biste nastavili"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Čvrsto pritisnite senzor"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Otisak prsta nije prepoznat. Probajte ponovo."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Obrišite senzor za otisak prsta i probajte ponovo"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Obrišite senzor i probajte ponovo"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Čvrsto pritisnite senzor"</string> @@ -702,8 +699,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"Ne vidi se lice. Držite telefon u visini očiju."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Mnogo se pomerate. Držite telefon mirno."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Ponovo registrujte lice."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"Lice nije prepoznato. Probajte ponovo."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Malo pomerite glavu"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Gledajte pravo u telefon"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Gledajte pravo u telefon"</string> diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml index 515a6a3bf4c3..42c5010397d8 100644 --- a/core/res/res/values-be/strings.xml +++ b/core/res/res/values-be/strings.xml @@ -436,10 +436,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Дазваляе праграме выкарыстоўваць актыўныя сэрвісы тыпу \"systemExempted\""</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"запуск актыўнага сэрвісу тыпу \"fileManagement\""</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"Праграма зможа выкарыстоўваць актыўныя сэрвісы тыпу \"fileManagement\""</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"запуск актыўнага сэрвісу тыпу \"mediaProcessing\""</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"Дазваляе праграме выкарыстоўваць актыўныя сэрвісы тыпу \"mediaProcessing\""</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"запуск актыўнага сэрвісу тыпу \"specialUse\""</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Дазваляе праграме выкарыстоўваць актыўныя сэрвісы тыпу \"specialUse\""</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"вымерыць прастору для захоўвання прыкладання"</string> @@ -638,8 +636,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Ужываць блакіроўку экрана"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Каб працягнуць, скарыстайце свой сродак блакіроўкі экрана"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Шчыльна прыкладзіце палец да сканера"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Адбітак пальца не распазнаны. Паўтарыце спробу."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Ачысціце сканер адбіткаў пальцаў і паўтарыце спробу"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Ачысціце сканер і паўтарыце спробу"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Шчыльна прыкладзіце палец да сканера"</string> @@ -703,8 +700,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"Не відаць твару. Трымайце тэлефон на ўзроўні вачэй."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Трымайце прыладу нерухома. Трымайце тэлефон роўна."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Паўтарыце рэгістрацыю твару."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"Твар не распазнаны. Паўтарыце спробу."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Крыху змяніце паставу галавы"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Глядзіце прама на экран тэлефона"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Глядзіце прама на экран тэлефона"</string> diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml index 4689e32faa3c..181746e107f9 100644 --- a/core/res/res/values-bg/strings.xml +++ b/core/res/res/values-bg/strings.xml @@ -434,10 +434,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Разрешава на приложението да се възползва от услуги на преден план от тип systemExempted"</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"Изпълнение на услуги на преден план от тип fileManagement"</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"Разрешава на приложението да се възползва от услуги на преден план от тип fileManagement"</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"изпълнение на услуги на преден план от тип mediaProcessing"</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"Разрешава на приложението да се възползва от услуги на преден план от тип mediaProcessing"</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"изпълнение на услуги на преден план от тип specialUse"</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Разрешава на приложението да се възползва от услуги на преден план от тип specialUse"</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"измерване на ползваното от приложението място в хранилището"</string> @@ -636,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Ползване на заключв. на екрана"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Въведете опцията си за заключване на екрана, за да продължите"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Натиснете добре върху сензора"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Отпечатъкът не е разпознат. Опитайте отново."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Почистете сензора за отпечатъци и опитайте отново"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Почистете сензора и опитайте отново"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Натиснете добре върху сензора"</string> @@ -701,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"Лицето не се вижда. Задръжте на нивото на очите."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Твърде много движение. Дръжте телефона неподвижно."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Моля, регистрирайте лицето си отново."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"Лицето не е разпознато. Опитайте отново."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Леко променете позицията на главата си"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Гледайте директно към телефона си"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Гледайте директно към телефона си"</string> diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml index d615cbeb0fd6..236fff52473f 100644 --- a/core/res/res/values-bn/strings.xml +++ b/core/res/res/values-bn/strings.xml @@ -434,10 +434,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"অ্যাপকে \"systemExempted\" সম্পর্কিত ফোরগ্রাউন্ড পরিষেবা ব্যবহার করার অনুমতি দেয়"</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"\"fileManagement\" সম্পর্কিত ফোরগ্রাউন্ড পরিষেবা রান করা"</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"অ্যাপকে \"fileManagement\" সম্পর্কিত ফোরগ্রাউন্ড পরিষেবা ব্যবহার করার অনুমতি দেয়"</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"\"mediaProcessing\" সম্পর্কিত ফোরগ্রাউন্ড পরিষেবা রান করা"</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"অ্যাপকে \"mediaProcessing\" সম্পর্কিত ফোরগ্রাউন্ড পরিষেবা ব্যবহার করার অনুমতি দেয়"</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"\"specialUse\" সম্পর্কিত ফোরগ্রাউন্ড পরিষেবা রান করান"</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"অ্যাপকে \"specialUse\" সম্পর্কিত ফোরগ্রাউন্ড পরিষেবা ব্যবহার করার অনুমতি দেয়"</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"অ্যাপ্লিকেশন সঞ্চয়স্থানের জায়গা পরিমাপ করে"</string> @@ -636,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"স্ক্রিন লক ব্যবহার করুন"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"চালিয়ে যেতে আপনার স্ক্রিন লক ব্যবহার করুন"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"সেন্সরে জোরে প্রেস করুন"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"ফিঙ্গারপ্রিন্ট শনাক্ত হয়নি। আবার চেষ্টা করুন।"</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"আঙ্গুলের ছাপের সেন্সর পরিষ্কার করে আবার চেষ্টা করুন"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"সেন্সর পরিষ্কার করে আবার চেষ্টা করুন"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"সেন্সরে জোরে প্রেস করুন"</string> @@ -701,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"আপনার মুখ দেখা যাচ্ছে না। ফোন আপনার চোখের সোজাসুজি ধরুন।"</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"খুব বেশি নড়ছে। ফোনটি যাতে না কাঁপে সেইভাবে ধরুন।"</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"আপনার মুখের ছবি আবার নথিভুক্ত করুন।"</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"মুখ চেনা যায়নি। আবার চেষ্টা করুন।"</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"আপনার মাথার পজিশন সামান্য পরিবর্তন করুন"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"আপনার ফোনের দিকে একদম সোজাসুজি তাকান"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"আপনার ফোনের দিকে একদম সোজাসুজি তাকান"</string> diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml index f110a24e0c3f..1da26049fa55 100644 --- a/core/res/res/values-bs/strings.xml +++ b/core/res/res/values-bs/strings.xml @@ -435,10 +435,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Dozvoljava aplikaciji da koristi usluge u prvom planu s vrstom \"systemExempted\""</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"pokreni uslugu u prvom planu s vrstom \"fileManagement\""</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"Dozvoljava aplikaciji da koristi usluge u prvom planu s vrstom \"fileManagement\""</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"pokreni uslugu u prvom planu s vrstom \"mediaProcessing\""</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"Dozvoljava aplikaciji da koristi usluge u prvom planu s vrstom \"mediaProcessing\""</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"pokreni uslugu u prvom planu s vrstom \"specialUse\""</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Dozvoljava aplikaciji da koristi usluge u prvom planu s vrstom \"specialUse\""</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"mjerenje prostora kojeg aplikacije zauzimaju u pohrani"</string> @@ -637,8 +635,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Koristi zaključavanje ekrana"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Unesite zaključavanje ekrana da nastavite"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Čvrsto pritisnite senzor"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Otisak prsta nije prepoznat. Pokušajte ponovo."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Očistite senzor za otisak prsta i pokušajte ponovo"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Očistite senzor i pokušajte ponovo"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Čvrsto pritisnite senzor"</string> @@ -702,8 +699,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"Lice se ne vidi. Držite telefon u visini očiju."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Previše pokreta. Držite telefon mirno."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Ponovo registrirajte lice."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"Lice nije prepoznato. Pokušajte ponovo."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Malo pomjerite glavu"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Gledajte direktno u telefon"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Gledajte direktno u telefon"</string> diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml index d9744dd5b96b..867a34dc7141 100644 --- a/core/res/res/values-ca/strings.xml +++ b/core/res/res/values-ca/strings.xml @@ -435,10 +435,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Permet que l\'aplicació utilitzi serveis en primer pla amb el tipus \"systemExempted\""</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"executa serveis en primer pla amb el tipus \"fileManagement\""</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"Permet que l\'aplicació utilitzi serveis en primer pla amb el tipus \"fileManagement\""</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"executar serveis en primer pla amb el tipus \"mediaProcessing\""</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"Permet que l\'aplicació utilitzi serveis en primer pla amb el tipus \"mediaProcessing\""</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"executa serveis en primer pla amb el tipus \"specialUse\""</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Permet que l\'aplicació utilitzi serveis en primer pla amb el tipus \"specialUse\""</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"mesura l\'espai d\'emmagatzematge d\'aplicacions"</string> @@ -637,8 +635,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Utilitza el bloqueig de pantalla"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Introdueix el teu bloqueig de pantalla per continuar"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Prem el sensor de manera ferma"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"L\'empremta digital no s\'ha reconegut. Torna-ho a provar."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Neteja el sensor d\'empremtes digitals i torna-ho a provar"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Neteja el sensor i torna-ho a provar"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Prem el sensor de manera ferma"</string> @@ -702,8 +699,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"No se\'t veu la cara. Mantén el telèfon a l\'altura dels ulls."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Massa moviment. Subjecta bé el telèfon."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Torna a registrar la teva cara."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"La cara no s\'ha reconegut. Torna-ho a provar."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Canvia lleugerament la posició del cap"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Mira més directament al telèfon"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Mira més directament al telèfon"</string> diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml index c72f07dee44c..2c173731cfa0 100644 --- a/core/res/res/values-cs/strings.xml +++ b/core/res/res/values-cs/strings.xml @@ -436,10 +436,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Umožňuje aplikaci používat služby v popředí typu „systemExempted“"</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"používat službu v popředí typu „fileManagement“"</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"Umožňuje aplikaci používat služby v popředí typu „fileManagement“"</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"používat službu v popředí typu mediaProcessing"</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"Umožňuje aplikaci používat služby v popředí typu mediaProjection"</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"používat službu v popředí typu „specialUse“"</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Umožňuje aplikaci používat služby v popředí typu „specialUse“"</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"výpočet místa pro ukládání aplikací"</string> @@ -638,8 +636,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Použít zámek obrazovky"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Pokračujte zadáním zámku obrazovky"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Pevně zatlačte na snímač"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Otisk prstu nebyl rozpoznán. Zkuste to znovu."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Vyčistěte snímač otisků prstů a zkuste to znovu"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Vyčistěte senzor a zkuste to znovu"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Pevně přitiskněte prst na snímač"</string> @@ -703,8 +700,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"Obličej není vidět. Držte telefon v úrovni očí."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Příliš mnoho pohybu. Držte telefon nehybně."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Zaznamenejte obličej znovu."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"Obličej nebyl rozpoznán. Zkuste to znovu."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Mírně pohněte hlavou"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Dívejte se přímo na telefon"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Dívejte se přímo na telefon"</string> diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml index f72c0c2db8d3..f04fd757c834 100644 --- a/core/res/res/values-da/strings.xml +++ b/core/res/res/values-da/strings.xml @@ -434,10 +434,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Tillader, at appen benytter tjenester af typen \"systemExempted\" i forgrunden"</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"kør tjenesten af typen \"fileManagement\" i forgrunden"</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"Tillader, at appen benytter tjenester af typen \"fileManagement\" i forgrunden"</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"kør tjenesten af typen \"mediaProcessing\" i forgrunden"</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"Tillader, at appen benytter tjenester af typen \"mediaProcessing\" i forgrunden"</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"kør tjenesten af typen \"specialUse\" i forgrunden"</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Tillader, at appen benytter tjenester af typen \"specialUse\" i forgrunden"</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"måle appens lagerplads"</string> @@ -636,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Brug skærmlås"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Angiv din skærmlås for at fortsætte"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Hold fingeren på sensoren"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Fingeraftrykket blev ikke genkendt. Prøv igen."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Rengør fingeraftrykssensoren, og prøv igen"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Rengør sensoren, og prøv igen"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Hold fingeren på sensoren"</string> @@ -701,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"Dit ansigt kan ikke registreres. Hold din telefon i øjenhøjde."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Der er for meget bevægelse. Hold telefonen stille."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Registrer dit ansigt igen."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"Ansigtet blev ikke genkendt. Prøv igen."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Flyt dit hoved en smule"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Kig mere direkte på din telefon"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Kig mere direkte på din telefon"</string> diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml index e03592cce867..d55ba9f25903 100644 --- a/core/res/res/values-de/strings.xml +++ b/core/res/res/values-de/strings.xml @@ -434,10 +434,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Ermöglicht der App, Vordergrunddienste mit dem Typ „systemExempted“ zu verwenden"</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"Dienste im Vordergrund mit dem Typ „fileManagement“ ausführen"</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"Ermöglicht der App, Dienste im Vordergrund mit dem Typ „fileManagement“ zu verwenden"</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"Vordergrunddienst des Typs „mediaProcessing“ ausführen"</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"Ermöglicht der App, Vordergrunddienste des Typs „mediaProcessing“ zu verwenden"</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"Vordergrunddienste mit dem Typ „specialUse“ ausführen"</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Ermöglicht der App, Vordergrunddienste mit dem Typ „specialUse“ zu verwenden"</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"Speicherplatz der App ermitteln"</string> @@ -636,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Displaysperre verwenden"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Displaysperre eingeben, um fortzufahren"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Drücke fest auf den Sensor"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Fingerabdruck nicht erkannt. Versuche es noch einmal."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Reinige den Fingerabdrucksensor und versuch es noch einmal"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Reinige den Sensor und versuche es noch einmal"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Drücke fest auf den Sensor"</string> @@ -701,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"Gesicht nicht erkannt. Smartphone auf Augenhöhe halten."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Zu viel Unruhe. Halte das Smartphone ruhig."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Bitte registriere dein Gesicht noch einmal."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"Gesicht nicht erkannt. Versuche es noch einmal."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Ändere die Position deines Kopfes leicht"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Sieh direkt auf dein Smartphone"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Sieh direkt auf dein Smartphone"</string> diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml index d9c94511f265..1346faff143f 100644 --- a/core/res/res/values-el/strings.xml +++ b/core/res/res/values-el/strings.xml @@ -434,10 +434,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Επιτρέπει στην εφαρμογή να χρησιμοποιεί τις υπηρεσίες στο προσκήνιο με τον τύπο \"systemExempted\""</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"εκτέλεση υπηρεσίας στο προσκήνιο με τον τύπο fileManagement"</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"Επιτρέπει στην εφαρμογή να χρησιμοποιεί τις υπηρεσίες στο προσκήνιο με τον τύπο fileManagement."</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"εκτέλεση υπηρεσίας στο προσκήνιο με τον τύπο \"mediaProcessing\""</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"Επιτρέπει στην εφαρμογή να χρησιμοποιεί τις υπηρεσίες στο προσκήνιο με τον τύπο \"mediaProcessing\""</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"εκτέλεση υπηρεσίας στο προσκήνιο με τον τύπο \"specialUse\""</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Επιτρέπει στην εφαρμογή να χρησιμοποιεί τις υπηρεσίες στο προσκήνιο με τον τύπο \"specialUse\""</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"υπολογίζει τον αποθηκευτικό χώρο εφαρμογής"</string> @@ -636,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Χρήση κλειδώματος οθόνης"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Χρησιμοποιήστε το κλείδωμα οθόνης για να συνεχίσετε"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Πιέστε σταθερά τον αισθητήρα"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Το δακτυλικό αποτύπωμα δεν αναγνωρίστηκε. Δοκιμάστε ξανά."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Καθαρίστε τον αισθητήρα δακτυλικών αποτυπωμάτων και δοκιμάστε ξανά"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Καθαρίστε τον αισθητήρα και δοκιμάστε ξανά"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Πιέστε σταθερά τον αισθητήρα"</string> @@ -701,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"Κρατήστε το τηλέφωνο στο ύψος των ματιών σας."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Πάρα πολλή κίνηση. Κρατήστε σταθερό το τηλέφωνο."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Καταχωρίστε ξανά το πρόσωπό σας."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"Το πρόσωπο δεν αναγνωρίστηκε. Δοκιμάστε ξανά."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Αλλάξτε ελαφρώς τη θέση του κεφαλιού σας"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Κοιτάξτε απευθείας το τηλέφωνό σας"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Κοιτάξτε απευθείας το τηλέφωνό σας"</string> diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml index fd801b5f710a..8f6bb190d1d1 100644 --- a/core/res/res/values-en-rAU/strings.xml +++ b/core/res/res/values-en-rAU/strings.xml @@ -434,10 +434,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Allows the app to make use of foreground services with the type \'systemExempted\'"</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"run foreground service with the type \'fileManagement\'"</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"Allows the app to make use of foreground services with the type \'fileManagement\'"</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"run foreground service with the type \'mediaProcessing\'"</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"Allows the app to make use of foreground services with the type \'mediaProcessing\'"</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"run foreground service with the type \'specialUse\'"</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Allows the app to make use of foreground services with the type \'specialUse\'"</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"measure app storage space"</string> @@ -636,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Use screen lock"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Enter your screen lock to continue"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Press firmly on the sensor"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Fingerprint not recognised. Try again."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Clean fingerprint sensor and try again"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Clean sensor and try again"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Press firmly on the sensor"</string> @@ -701,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"Can’t see your face. Hold your phone at eye level."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Too much motion. Hold phone steady."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Please re-enroll your face."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"Face not recognised. Try again."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Change the position of your head slightly"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Look more directly at your phone"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Look more directly at your phone"</string> diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml index bf9acc103579..9129b820df6d 100644 --- a/core/res/res/values-en-rCA/strings.xml +++ b/core/res/res/values-en-rCA/strings.xml @@ -634,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Use screen lock"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Enter your screen lock to continue"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Press firmly on the sensor"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Fingerprint not recognized. Try again."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Clean fingerprint sensor and try again"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Clean sensor and try again"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Press firmly on the sensor"</string> @@ -699,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"Can’t see your face. Hold your phone at eye level."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Too much motion. Hold phone steady."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Please re-enroll your face."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"Face not recognized. Try again."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Change the position of your head slightly"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Look more directly at your phone"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Look more directly at your phone"</string> diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml index 662247ea6dc9..dd7f4a72ae7a 100644 --- a/core/res/res/values-en-rGB/strings.xml +++ b/core/res/res/values-en-rGB/strings.xml @@ -434,10 +434,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Allows the app to make use of foreground services with the type \'systemExempted\'"</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"run foreground service with the type \'fileManagement\'"</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"Allows the app to make use of foreground services with the type \'fileManagement\'"</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"run foreground service with the type \'mediaProcessing\'"</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"Allows the app to make use of foreground services with the type \'mediaProcessing\'"</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"run foreground service with the type \'specialUse\'"</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Allows the app to make use of foreground services with the type \'specialUse\'"</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"measure app storage space"</string> @@ -636,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Use screen lock"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Enter your screen lock to continue"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Press firmly on the sensor"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Fingerprint not recognised. Try again."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Clean fingerprint sensor and try again"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Clean sensor and try again"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Press firmly on the sensor"</string> @@ -701,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"Can’t see your face. Hold your phone at eye level."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Too much motion. Hold phone steady."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Please re-enroll your face."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"Face not recognised. Try again."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Change the position of your head slightly"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Look more directly at your phone"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Look more directly at your phone"</string> diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml index e7278d58a7bd..b652512133b4 100644 --- a/core/res/res/values-en-rIN/strings.xml +++ b/core/res/res/values-en-rIN/strings.xml @@ -434,10 +434,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Allows the app to make use of foreground services with the type \'systemExempted\'"</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"run foreground service with the type \'fileManagement\'"</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"Allows the app to make use of foreground services with the type \'fileManagement\'"</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"run foreground service with the type \'mediaProcessing\'"</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"Allows the app to make use of foreground services with the type \'mediaProcessing\'"</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"run foreground service with the type \'specialUse\'"</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Allows the app to make use of foreground services with the type \'specialUse\'"</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"measure app storage space"</string> @@ -636,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Use screen lock"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Enter your screen lock to continue"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Press firmly on the sensor"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Fingerprint not recognised. Try again."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Clean fingerprint sensor and try again"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Clean sensor and try again"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Press firmly on the sensor"</string> @@ -701,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"Can’t see your face. Hold your phone at eye level."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Too much motion. Hold phone steady."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Please re-enroll your face."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"Face not recognised. Try again."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Change the position of your head slightly"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Look more directly at your phone"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Look more directly at your phone"</string> diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml index 51ab2cafd3f9..5ed9d11cd509 100644 --- a/core/res/res/values-en-rXC/strings.xml +++ b/core/res/res/values-en-rXC/strings.xml @@ -634,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Use screen lock"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Enter your screen lock to continue"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Press firmly on the sensor"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Fingerprint not recognized. Try again."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Clean fingerprint sensor and try again"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Clean sensor and try again"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Press firmly on the sensor"</string> @@ -699,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"Can’t see your face. Hold your phone at eye level."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Too much motion. Hold phone steady."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Please re-enroll your face."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"Face not recognized. Try again."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Change the position of your head slightly"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Look more directly at your phone"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Look more directly at your phone"</string> diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml index 8686e19be5c5..bc94eed5c145 100644 --- a/core/res/res/values-es-rUS/strings.xml +++ b/core/res/res/values-es-rUS/strings.xml @@ -435,10 +435,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Permite que la app use servicios en primer plano con el tipo \"systemExempted\""</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"Ejecutar un servicio en primer plano con el tipo \"fileManagement\""</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"Permite que la app use servicios en primer plano con el tipo \"fileManagement\""</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"Ejecutar un servicio en primer plano con el tipo \"mediaProcessing\""</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"Permite que la app use servicios en primer plano con el tipo \"mediaProcessing\""</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"Ejecuta un servicio en primer plano con el tipo \"specialUse\""</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Permite que la app use servicios en primer plano con el tipo \"specialUse\""</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"medir el espacio de almacenamiento de la aplicación"</string> @@ -637,8 +635,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Usar bloqueo de pantalla"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Ingresa tu bloqueo de pantalla para continuar"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Presiona el sensor con firmeza"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"No se reconoció la huella dactilar. Vuelve a intentarlo."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Limpia el sensor de huellas dactilares y vuelve a intentarlo"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Limpia el sensor y vuelve a intentarlo"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Presiona el sensor con firmeza"</string> @@ -702,8 +699,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"No se te ve el rostro. Sostén el teléfono a la altura de los ojos."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Te estás moviendo demasiado. No muevas el teléfono"</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Vuelve a registrar tu rostro."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"No se reconoció el rostro. Vuelve a intentarlo."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Cambia levemente la posición de la cabeza"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Mira directamente al teléfono"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Mira directamente al teléfono"</string> diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml index 8f57a078736f..c65e67058b0d 100644 --- a/core/res/res/values-es/strings.xml +++ b/core/res/res/values-es/strings.xml @@ -435,10 +435,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Permite que la aplicación use servicios en primer plano con el tipo \"systemExempted\""</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"ejecutar un servicio en primer plano con el tipo \"fileManagement\""</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"Permite que la aplicación use servicios en primer plano con el tipo \"fileManagement\""</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"ejecutar un servicio en primer plano con el tipo \"mediaProcessing\""</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"Permite que la aplicación use servicios en primer plano con el tipo \"mediaProcessing\""</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"ejecutar un servicio en primer plano con el tipo \"specialUse\""</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Permite que la aplicación use servicios en primer plano con el tipo \"specialUse\""</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"medir el espacio de almacenamiento de la aplicación"</string> @@ -637,8 +635,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Usar bloqueo de pantalla"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Introduce tu bloqueo de pantalla para continuar"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Pulsa firmemente el sensor"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Huella digital no reconocida. Inténtalo de nuevo."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Limpia el sensor de huellas digitales e inténtalo de nuevo"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Limpia el sensor e inténtalo de nuevo"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Pulsa firmemente el sensor"</string> @@ -702,8 +699,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"No se detecta tu cara. Sujeta el teléfono a la altura de los ojos."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"El teléfono se mueve demasiado. Mantenlo quieto."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Vuelve a registrar tu cara."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"Cara no reconocida. Inténtalo de nuevo."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Cambia ligeramente la posición de tu cabeza"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Mira al teléfono de forma más directa"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Mira al teléfono de forma más directa"</string> diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml index e814c96e217d..9c7cc1b0b518 100644 --- a/core/res/res/values-et/strings.xml +++ b/core/res/res/values-et/strings.xml @@ -434,10 +434,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Lubab rakendusel kasutada esiplaanil olevaid teenuseid, mille tüüp on „systemExempted“."</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"sellise esiplaanil oleva teenuse käitamine, mille tüüp on „fileManagement“"</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"Lubab rakendusel kasutada esiplaanil olevaid teenuseid, mille tüüp on „fileManagement“"</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"sellise esiplaanil oleva teenuse käitamine, mille tüüp on „mediaProcessing“"</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"Lubab rakendusel kasutada esiplaanil olevaid teenuseid, mille tüüp on „mediaProcessing“."</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"sellise esiplaanil oleva teenuse käitamine, mille tüüp on „specialUse“"</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Lubab rakendusel kasutada esiplaanil olevaid teenuseid, mille tüüp on „specialUse“."</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"Rakenduse mäluruumi mõõtmine"</string> @@ -636,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Ekraaniluku kasutamine"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Jätkamiseks sisestage oma ekraanilukk"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Vajutage kindlalt andurile"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Sõrmejälge ei tuvastatud. Proovige uuesti."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Puhastage sõrmejäljeandur ja proovige uuesti"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Puhastage andur ja proovige uuesti"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Vajutage kindlalt andurile"</string> @@ -701,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"Teie nägu ei ole näha. Hoidke telefoni silmade kõrgusel."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Liiga palju liikumist. Hoidke telefoni paigal."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Registreerige oma nägu uuesti."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"Nägu ei tuvastatud. Proovige uuesti."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Muutke pisut oma pea asendit"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Vaadake otse telefoni"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Vaadake otse telefoni"</string> diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml index feabc8f90fce..847fe5621988 100644 --- a/core/res/res/values-eu/strings.xml +++ b/core/res/res/values-eu/strings.xml @@ -347,51 +347,51 @@ <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Pantaila-argazkiak atera ditzake."</string> <string name="dream_preview_title" msgid="5570751491996100804">"Aurrebista, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string> <string name="permlab_statusBar" msgid="8798267849526214017">"desgaitu edo aldatu egoera-barra"</string> - <string name="permdesc_statusBar" msgid="5809162768651019642">"Egoera-barra desgaitzea edo sistema-ikonoak gehitzea edo kentzea baimentzen die aplikazioei."</string> + <string name="permdesc_statusBar" msgid="5809162768651019642">"Egoera-barra desgaitzeko edo sistema-ikonoak gehitzeko edo kentzeko baimena ematen dio aplikazioari."</string> <string name="permlab_statusBarService" msgid="2523421018081437981">"bihurtu egoera-barra"</string> - <string name="permdesc_statusBarService" msgid="6652917399085712557">"Egoera-barra izateko baimena ematen die aplikazioei."</string> + <string name="permdesc_statusBarService" msgid="6652917399085712557">"Egoera-barra izateko baimena ematen dio aplikazioari."</string> <string name="permlab_expandStatusBar" msgid="1184232794782141698">"zabaldu/tolestu egoera-barra"</string> - <string name="permdesc_expandStatusBar" msgid="7180756900448498536">"Egoera-barra zabaltzeko edo tolesteko baimena ematen die aplikazioei."</string> + <string name="permdesc_expandStatusBar" msgid="7180756900448498536">"Egoera-barra zabaltzeko edo tolesteko baimena ematen dio aplikazioari."</string> <string name="permlab_fullScreenIntent" msgid="4310888199502509104">"blokeatutako gailu batean jakinarazpenak pantaila osoko jarduera gisa bistaratzea"</string> - <string name="permdesc_fullScreenIntent" msgid="1100721419406643997">"Blokeatutako gailu batean jakinarazpenak pantaila osoko jarduera gisa bistaratzeko baimena ematen die aplikazioei"</string> + <string name="permdesc_fullScreenIntent" msgid="1100721419406643997">"Blokeatutako gailu batean jakinarazpenak pantaila osoko jarduera gisa bistaratzeko baimena ematen dio aplikazioari"</string> <string name="permlab_install_shortcut" msgid="7451554307502256221">"Instalatu lasterbideak"</string> <string name="permdesc_install_shortcut" msgid="4476328467240212503">"Erabiltzaileak ezer egin gabe hasierako pantailan lasterbideak gehitzeko aukera ematen die aplikazioei."</string> <string name="permlab_uninstall_shortcut" msgid="295263654781900390">"desinstalatu lasterbideak"</string> <string name="permdesc_uninstall_shortcut" msgid="1924735350988629188">"Erabiltzaileak ezer egin gabe hasierako pantailako lasterbideak kentzeko aukera ematen die aplikazioei."</string> <string name="permlab_processOutgoingCalls" msgid="4075056020714266558">"birbideratu irteerako deiak"</string> - <string name="permdesc_processOutgoingCalls" msgid="7833149750590606334">"Irteerako deian markatutako zenbakia ikusteko baimena ematen die aplikazioei, deia beste zenbaki batera birbideratzeko edo deia bertan behera uzteko aukerarekin."</string> + <string name="permdesc_processOutgoingCalls" msgid="7833149750590606334">"Irteerako deian markatutako zenbakia ikusteko baimena ematen dio aplikazioari, deia beste zenbaki batera birbideratzeko edo deia bertan behera uzteko aukerarekin."</string> <string name="permlab_answerPhoneCalls" msgid="4131324833663725855">"erantzun telefono-deiak"</string> - <string name="permdesc_answerPhoneCalls" msgid="894386681983116838">"Sarrerako deiak hartzea baimentzen die aplikazioei."</string> + <string name="permdesc_answerPhoneCalls" msgid="894386681983116838">"Sarrerako deiak hartzeko baimena ematen dio aplikazioari."</string> <string name="permlab_receiveSms" msgid="505961632050451881">"jaso testu-mezuak (SMSak)"</string> - <string name="permdesc_receiveSms" msgid="1797345626687832285">"SMS mezuak jasotzeko eta prozesatzeko baimena ematen die aplikazioei. Horrela, aplikazioak gailura bidalitako mezuak kontrola eta ezaba ditzake zuri erakutsi gabe."</string> + <string name="permdesc_receiveSms" msgid="1797345626687832285">"SMS mezuak jasotzeko eta prozesatzeko baimena ematen dio aplikazioari. Horrela, aplikazioak gailura bidalitako mezuak kontrola eta ezaba ditzake zuri erakutsi gabe."</string> <string name="permlab_receiveMms" msgid="4000650116674380275">"jaso testu-mezuak (MMSak)"</string> - <string name="permdesc_receiveMms" msgid="958102423732219710">"MMS mezuak jasotzeko eta prozesatzeko baimena ematen die aplikazioei. Horrela, aplikazioak gailura bidalitako mezuak kontrola eta ezaba ditzake zuri erakutsi gabe."</string> + <string name="permdesc_receiveMms" msgid="958102423732219710">"MMS mezuak jasotzeko eta prozesatzeko baimena ematen dio aplikazioari. Horrela, aplikazioak gailura bidalitako mezuak kontrola eta ezaba ditzake zuri erakutsi gabe."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"desbideratu sare mugikor bidezko igorpen-mezuak"</string> - <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Sare mugikor bidezko iragarpen-modulura lotzeko baimena ematen die aplikazioei, sare mugikor bidezko iragarpen-mezuak jaso ahala desbideratu ahal izateko. Sare mugikor bidezko iragarpen-alertak kokapen batzuetan entregatzen dira larrialdi-egoeren berri emateko. Sare mugikor bidezko larrialdi-iragarpenak jasotzean, asmo txarreko aplikazioek gailuaren errendimenduari edota funtzionamenduari eragin diezaiokete."</string> + <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Sare mugikor bidezko iragarpen-modulura lotzeko baimena ematen dio aplikazioari, sare mugikor bidezko iragarpen-mezuak jaso ahala desbideratu ahal izateko. Sare mugikor bidezko iragarpen-alertak kokapen batzuetan entregatzen dira larrialdi-egoeren berri emateko. Sare mugikor bidezko larrialdi-iragarpenak jasotzean, asmo txarreko aplikazioek gailuaren errendimenduari edota funtzionamenduari eragin diezaiokete."</string> <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Kudeatu abian dauden deiak"</string> <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Gailuak jasotzen dituen deiei buruzko xehetasunak ikusteko eta dei horiek kontrolatzeko baimena ematen die aplikazioei."</string> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"irakurri sare mugikor bidezko igorpen-mezuak"</string> - <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Gailuak jasotako sare mugikor bidezko igorpen-mezuak irakurtzeko baimena ematen die aplikazioei. Sare mugikor bidezko igorpen-alertak kokapen batzuetan ematen dira larrialdi-egoeren berri emateko. Asmo txarreko aplikazioek gailuaren errendimendua edo funtzionamendua oztopa dezakete larrialdi-igorpen horietako bat jasotzen denean."</string> + <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Gailuak jasotako sare mugikor bidezko igorpen-mezuak irakurtzeko baimena ematen dio aplikazioari. Sare mugikor bidezko igorpen-alertak kokapen batzuetan ematen dira larrialdi-egoeren berri emateko. Asmo txarreko aplikazioek gailuaren errendimendua edo funtzionamendua oztopa dezakete larrialdi-igorpen horietako bat jasotzen denean."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"irakurri harpidetutako jarioak"</string> - <string name="permdesc_subscribedFeedsRead" msgid="6911349196661811865">"Une horretan sinkronizatutako jarioei buruzko xehetasunak lortzeko baimena ematen die aplikazioei."</string> + <string name="permdesc_subscribedFeedsRead" msgid="6911349196661811865">"Une horretan sinkronizatutako jarioei buruzko xehetasunak lortzeko baimena ematen dio aplikazioari."</string> <string name="permlab_sendSms" msgid="7757368721742014252">"bidali eta ikusi SMS mezuak"</string> - <string name="permdesc_sendSms" msgid="6757089798435130769">"SMS mezuak bidaltzeko baimena ematen die aplikazioei. Horrela, ustekabeko gastuak eragin daitezke. Asmo txarreko aplikazioek erabil dezakete zuk berretsi gabeko mezuak bidalita gastuak eragiteko."</string> + <string name="permdesc_sendSms" msgid="6757089798435130769">"SMS mezuak bidaltzeko baimena ematen dio aplikazioari. Horrela, ustekabeko gastuak eragin daitezke. Asmo txarreko aplikazioek erabil dezakete zuk berretsi gabeko mezuak bidalita gastuak eragiteko."</string> <string name="permlab_readSms" msgid="5164176626258800297">"irakurri testu-mezuak (SMSak edo MMSak)"</string> <string name="permdesc_readSms" product="tablet" msgid="7912990447198112829">"Aplikazioak tabletan gordetako SMS mezu (testu-mezu) guztiak irakur ditzake."</string> <string name="permdesc_readSms" product="tv" msgid="3054753345758011986">"Aplikazioek Android TV gailuan gordetako SMS (testu) mezu guztiak irakur ditzakete."</string> <string name="permdesc_readSms" product="default" msgid="774753371111699782">"Aplikazioak telefonoan gordetako SMS mezu (testu-mezu) guztiak irakur ditzake."</string> <string name="permlab_receiveWapPush" msgid="4223747702856929056">"jaso testu-mezuak (WAP bidezkoak)"</string> - <string name="permdesc_receiveWapPush" msgid="1638677888301778457">"WAP mezuak jasotzeko eta prozesatzeko baimena ematen die aplikazioei. Horrela, aplikazioak, besteak beste, gailura bidalitako mezuak kontrola eta ezaba ditzake zuri erakutsi gabe."</string> + <string name="permdesc_receiveWapPush" msgid="1638677888301778457">"WAP mezuak jasotzeko eta prozesatzeko baimena ematen dio aplikazioari. Horrela, aplikazioak, besteak beste, gailura bidalitako mezuak kontrola eta ezaba ditzake zuri erakutsi gabe."</string> <string name="permlab_getTasks" msgid="7460048811831750262">"eskuratu abian diren aplikazioak"</string> - <string name="permdesc_getTasks" msgid="7388138607018233726">"Une honetan edo duela gutxi exekutatutako zereginei buruzko informazioa lortzeko baimena ematen die aplikazioei. Horrela, aplikazioak gailuan erabiltzen ari diren aplikazioei buruzko informazioa ezagut dezake."</string> + <string name="permdesc_getTasks" msgid="7388138607018233726">"Une honetan edo duela gutxi exekutatutako zereginei buruzko informazioa lortzeko baimena ematen dio aplikazioari. Horrela, aplikazioak gailuan erabiltzen ari diren aplikazioei buruzko informazioa ezagut dezake."</string> <string name="permlab_manageProfileAndDeviceOwners" msgid="639849495253987493">"kudeatu profilen eta gailuen jabeak"</string> <string name="permdesc_manageProfileAndDeviceOwners" msgid="7304240671781989283">"Profilaren eta gailuaren jabeak zehazteko baimena ematen die aplikazioei."</string> <string name="permlab_reorderTasks" msgid="7598562301992923804">"ordenatu abian diren aplikazioak"</string> - <string name="permdesc_reorderTasks" msgid="8796089937352344183">"Zereginak aurreko eta atzeko planora eramateko baimena ematen die aplikazioei. Aplikazioak zuk ezer egin gabe egin dezake hori."</string> + <string name="permdesc_reorderTasks" msgid="8796089937352344183">"Zereginak aurreko eta atzeko planora eramateko baimena ematen dio aplikazioari. Aplikazioak zuk ezer egin gabe egin dezake hori."</string> <string name="permlab_enableCarMode" msgid="893019409519325311">"gaitu auto modua"</string> - <string name="permdesc_enableCarMode" msgid="56419168820473508">"Auto modua gaitzea baimentzen die aplikazioei."</string> + <string name="permdesc_enableCarMode" msgid="56419168820473508">"Auto modua gaitzeko baimena ematen dio aplikazioari."</string> <string name="permlab_killBackgroundProcesses" msgid="6559320515561928348">"itxi beste aplikazioak"</string> - <string name="permdesc_killBackgroundProcesses" msgid="2357013583055434685">"Beste aplikazioen atzeko planoko prozesuak amaitzeko baimena ematen die aplikazioei. Horrela, agian aplikazio batzuk exekutatzeari utziko zaio."</string> + <string name="permdesc_killBackgroundProcesses" msgid="2357013583055434685">"Beste aplikazioen atzeko planoko prozesuak amaitzeko baimena ematen dio aplikazioari. Horrela, agian aplikazio batzuk exekutatzeari utziko zaio."</string> <string name="permlab_systemAlertWindow" msgid="5757218350944719065">"agertu beste aplikazio batzuen gainean"</string> <string name="permdesc_systemAlertWindow" msgid="1145660714855738308">"Beste aplikazio batzuen edo pantailako beste zati batzuen gainean ager daiteke aplikazioa. Aplikazioaren funtzionamendu normala oztopa dezake eta beste aplikazio batzuen itxura alda dezake."</string> <string name="permlab_hideOverlayWindows" msgid="6382697828482271802">"ezkutatu gainjarritako aplikazioak"</string> @@ -405,11 +405,11 @@ <string name="permlab_use_exact_alarm" msgid="348045139777131552">"antolatu alarmak edo gertaera-abisuak"</string> <string name="permdesc_use_exact_alarm" msgid="7033761461886938912">"Aplikazioak hainbat ekintza programa ditzake; adibidez, alarmak eta abisuak, etorkizuneko une batean jakinarazpen bat jaso dezazun."</string> <string name="permlab_persistentActivity" msgid="464970041740567970">"izan aplikazioa beti abian"</string> - <string name="permdesc_persistentActivity" product="tablet" msgid="6055271149187369916">"Beren zati batzuk memoria modu iraunkorrean ezartzeko baimena ematen die aplikazioei. Horrela, beste aplikazioek erabilgarri duten memoria murritz daiteke eta tableta motel daiteke."</string> - <string name="permdesc_persistentActivity" product="tv" msgid="6800526387664131321">"Beren zati batzuk memorian modu iraunkorrean ezartzeko baimena ematen die aplikazioei. Ondorioz, beste aplikazioek memoria gutxiago izan lezakete erabilgarri, eta Android TV gailuak motelago funtziona lezake."</string> - <string name="permdesc_persistentActivity" product="default" msgid="1914841924366562051">"Beren zati batzuk memoria modu iraunkorrean ezartzeko baimena ematen die aplikazioei. Horrela, beste aplikazioek erabilgarri duten memoria murritz daiteke eta telefonoa motel daiteke."</string> + <string name="permdesc_persistentActivity" product="tablet" msgid="6055271149187369916">"Bere zati batzuk memoria modu iraunkorrean ezartzeko baimena ematen dio aplikazioari. Horrela, beste aplikazioek erabilgarri duten memoria murritz daiteke eta tableta motel daiteke."</string> + <string name="permdesc_persistentActivity" product="tv" msgid="6800526387664131321">"Bere zati batzuk memorian modu iraunkorrean ezartzeko baimena ematen dio aplikazioari. Ondorioz, beste aplikazioek memoria gutxiago izan lezakete erabilgarri, eta Android TV gailuak motelago funtziona lezake."</string> + <string name="permdesc_persistentActivity" product="default" msgid="1914841924366562051">"Beren zati batzuk memoria modu iraunkorrean ezartzeko baimena ematen dio aplikazioari. Horrela, beste aplikazioek erabilgarri duten memoria murritz daiteke eta telefonoa motel daiteke."</string> <string name="permlab_foregroundService" msgid="1768855976818467491">"abiarazi zerbitzuak aurreko planoan"</string> - <string name="permdesc_foregroundService" msgid="8720071450020922795">"Aurreko planoko zerbitzuak erabiltzea baimentzen dio aplikazioari."</string> + <string name="permdesc_foregroundService" msgid="8720071450020922795">"Aurreko planoko zerbitzuak erabiltzeko baimena ematen dio aplikazioari."</string> <string name="permlab_foregroundServiceCamera" msgid="7814751737955715297">"exekutatu aurreko planoko zerbitzu bat (camera motakoa)"</string> <string name="permdesc_foregroundServiceCamera" msgid="6973701931250595727">"Aurreko planoko zerbitzuak (camera motakoak) erabiltzeko baimena ematen dio aplikazioari"</string> <string name="permlab_foregroundServiceConnectedDevice" msgid="3019650546176872501">"exekutatu aurreko planoko zerbitzu bat (connectedDevice motakoa)"</string> @@ -433,43 +433,41 @@ <string name="permlab_foregroundServiceSystemExempted" msgid="1597663713590612685">"exekutatu aurreko planoko zerbitzu bat (systemExempted motakoa)"</string> <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Aurreko planoko zerbitzuak (systemExempted motakoak) erabiltzeko baimena ematen dio aplikazioari"</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"exekutatu aurreko planoko zerbitzu bat (fileManagement motakoa)"</string> - <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"Aurreko planoko zerbitzuak (fileManagement motakoak) erabiltzeko baimena ematen die aplikazioei."</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"Aurreko planoko zerbitzuak (fileManagement motakoak) erabiltzeko baimena ematen dio aplikazioari"</string> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"aurreko planoko zerbitzu bat exekutatu (mediaProcessing motakoa)"</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"Aurreko planoko zerbitzuak (mediaProcessing motakoak) erabiltzeko baimena ematen dio aplikazioari"</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"exekutatu aurreko planoko zerbitzu bat (specialUse motakoa)"</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Aurreko planoko zerbitzuak (specialUse motakoak) erabiltzeko baimena ematen dio aplikazioari"</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"neurtu aplikazioen biltegiratzeko tokia"</string> - <string name="permdesc_getPackageSize" msgid="742743530909966782">"Bere kodea, datuak eta cache-tamainak eskuratzeko baimena ematen die aplikazioei."</string> + <string name="permdesc_getPackageSize" msgid="742743530909966782">"Bere kodea, datuak eta cache-tamainak eskuratzeko baimena ematen dio aplikazioari."</string> <string name="permlab_writeSettings" msgid="8057285063719277394">"aldatu sistemaren ezarpenak"</string> - <string name="permdesc_writeSettings" msgid="8293047411196067188">"Sistemaren ezarpenen datuak aldatzeko baimena ematen die aplikazioei. Asmo txarreko aplikazioek sistemaren konfigurazioa hondatzeko erabil dezakete."</string> + <string name="permdesc_writeSettings" msgid="8293047411196067188">"Sistemaren ezarpenen datuak aldatzeko baimena ematen dio aplikazioari. Asmo txarreko aplikazioek sistemaren konfigurazioa hondatzeko erabil dezakete."</string> <string name="permlab_receiveBootCompleted" msgid="6643339400247325379">"exekutatu abiaraztean"</string> - <string name="permdesc_receiveBootCompleted" product="tablet" msgid="5565659082718177484">"Sistema berrabiarazi bezain laster abiarazteko baimena ematen die aplikazioei. Horrela, agian denbora gehiago beharko du tabletak abiarazteko, eta tabletaren funtzionamendu orokorra mantso daiteke, baimen hori duten aplikazioak beti abian egongo baitira."</string> - <string name="permdesc_receiveBootCompleted" product="tv" msgid="4900842256047614307">"Sistema abiarazi bezain laster beren burua abiarazteko baimena ematen die aplikazioei. Baliteke denbora gehiago behar izatea Android TV gailua abiarazteko eta aplikazioek gailua orokorrean mantsoago ibilarazteko baimena izatea, beti abian izango baita."</string> - <string name="permdesc_receiveBootCompleted" product="default" msgid="7912677044558690092">"Sistema berrabiarazi bezain laster abiarazteko baimena ematen die aplikazioei. Horrela, agian denbora gehiago beharko du telefonoak abiarazteko, eta telefonoaren funtzionamendu orokorra mantso daiteke, baimen hori duten aplikazioak beti abian egongo baitira."</string> + <string name="permdesc_receiveBootCompleted" product="tablet" msgid="5565659082718177484">"Sistema berrabiarazi bezain laster abiarazteko baimena ematen dio aplikazioari. Horrela, agian denbora gehiago beharko du tabletak abiarazteko, eta tabletaren funtzionamendu orokorra mantso daiteke, baimen hori duten aplikazioak beti abian egongo baitira."</string> + <string name="permdesc_receiveBootCompleted" product="tv" msgid="4900842256047614307">"Sistema abiarazi bezain laster bere burua abiarazteko baimena ematen dio aplikazioari. Baliteke denbora gehiago behar izatea Android TV gailua abiarazteko eta aplikazioak gailua orokorrean mantsoago ibilarazteko baimena izatea, beti abian izango baita."</string> + <string name="permdesc_receiveBootCompleted" product="default" msgid="7912677044558690092">"Sistema berrabiarazi bezain laster abiarazteko baimena ematen dio aplikazioari. Horrela, agian denbora gehiago beharko du telefonoak abiarazteko, eta telefonoaren funtzionamendu orokorra mantso daiteke, baimen hori duten aplikazioak beti abian egongo baitira."</string> <string name="permlab_broadcastSticky" msgid="4552241916400572230">"bidali igorpen erakargarria"</string> - <string name="permdesc_broadcastSticky" product="tablet" msgid="5058486069846384013">"Igorpen iraunkorrak emateko baimena ematen die; horiek igorpena amaitu ondoren mantentzen dira. Gehiegi erabiliz gero, tableta motel edo ezegonkor ibiliko da, memoria gehiago erabiliko delako."</string> - <string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Igorpen iraunkorrak egiteko baimena ematen die aplikazioei. Igorpena amaitu ondoren ere igortzen jarraitzen dute igorpen iraunkorrek. Gehiegi erabiliz gero, Android TV gailua motel edo ezegonkor ibiliko da, memoria gehiago erabiliko delako."</string> - <string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Igorpen iraunkorrak emateko baimena ematen die; horiek igorpena amaitu ondoren mantentzen dira. Gehiegi erabiliz gero, telefonoa motel edo ezegonkor ibiliko da, memoria gehiago erabiliko delako."</string> + <string name="permdesc_broadcastSticky" product="tablet" msgid="5058486069846384013">"Igorpen iraunkorrak emateko baimena ematen dio aplikazioari; horiek igorpena amaitu ondoren mantentzen dira. Gehiegi erabiliz gero, tableta motel edo ezegonkor ibiliko da, memoria gehiago erabiliko delako."</string> + <string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"Igorpen iraunkorrak egiteko baimena ematen dio aplikazioari. Igorpena amaitu ondoren ere igortzen jarraitzen dute igorpen iraunkorrek. Gehiegi erabiliz gero, Android TV gailua motel edo ezegonkor ibiliko da, memoria gehiago erabiliko delako."</string> + <string name="permdesc_broadcastSticky" product="default" msgid="134529339678913453">"Igorpen iraunkorrak emateko baimena ematen dio aplikazioari; horiek igorpena amaitu ondoren mantentzen dira. Gehiegi erabiliz gero, telefonoa motel edo ezegonkor ibiliko da, memoria gehiago erabiliko delako."</string> <string name="permlab_readContacts" msgid="8776395111787429099">"irakurri kontaktuak"</string> - <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Tabletan gordetako kontaktuei buruzko datuak irakurtzeko baimena ematen die aplikazioei. Kontaktuak sortu dituzten tabletako kontuak ere atzitu ahalko dituzte aplikazioek. Horrek barnean hartuko ditu instalatutako aplikazioek sortutako kontuak, agian. Baimen horrekin, kontaktuen datuak gorde ditzakete aplikazioek, eta baliteke asmo txarreko aplikazioek zuk jakin gabe partekatzea datu horiek."</string> - <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Android TV gailuan gordetako kontaktuei buruzko datuak irakurtzeko baimena ematen die aplikazioei. Kontaktuak sortu dituzten Android TV gailuko kontuak ere atzitu ahalko dituzte aplikazioek. Horrek barnean hartuko ditu instalatutako aplikazioek sortutako kontuak, agian. Baimen horrekin, kontaktuen datuak gorde ditzakete aplikazioek, eta baliteke asmo txarreko aplikazioek zuk jakin gabe partekatzea datu horiek."</string> - <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Telefonoan gordetako kontaktuei buruzko datuak irakurtzeko baimena ematen die aplikazioei. Kontaktuak sortu dituzten telefonoko kontuak ere atzitu ahalko dituzte aplikazioek. Horrek barnean hartuko ditu instalatutako aplikazioek sortutako kontuak, agian. Baimen horrekin, kontaktuen datuak gorde ditzakete aplikazioek, eta baliteke asmo txarreko aplikazioek zuk jakin gabe partekatzea datu horiek."</string> + <string name="permdesc_readContacts" product="tablet" msgid="6430093481659992692">"Tabletan gordetako kontaktuei buruzko datuak irakurtzeko baimena ematen dio aplikazioari. Kontaktuak sortu dituzten tabletako kontuak ere atzitu ahalko ditu aplikazioak. Horrek barnean hartuko ditu instalatutako aplikazioak sortutako kontuak, agian. Baimen horrekin, kontaktuen datuak gorde ditzake aplikazioak, eta baliteke asmo txarreko aplikazioek zuk jakin gabe partekatzea datu horiek."</string> + <string name="permdesc_readContacts" product="tv" msgid="8400138591135554789">"Android TV gailuan gordetako kontaktuei buruzko datuak irakurtzeko baimena ematen dio aplikazioari. Kontaktuak sortu dituzten Android TV gailuko kontuak ere atzitu ahalko ditu aplikazioak. Horrek barnean hartuko ditu instalatutako aplikazioak sortutako kontuak, agian. Baimen horrekin, kontaktuen datuak gorde ditzake aplikazioak, eta baliteke asmo txarreko aplikazioek zuk jakin gabe partekatzea datu horiek."</string> + <string name="permdesc_readContacts" product="default" msgid="4911989776203207644">"Telefonoan gordetako kontaktuei buruzko datuak irakurtzeko baimena ematen dio aplikazioari. Kontaktuak sortu dituzten telefonoko kontuak ere atzitu ahalko ditu aplikazioak. Horrek barnean hartuko ditu instalatutako aplikazioak sortutako kontuak, agian. Baimen horrekin, kontaktuen datuak gorde ditzake aplikazioak, eta baliteke asmo txarreko aplikazioek zuk jakin gabe partekatzea datu horiek."</string> <string name="permlab_writeContacts" msgid="8919430536404830430">"aldatu kontaktuak"</string> - <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Tabletan gordetako kontaktuei buruzko datuak aldatzeko baimena ematen die aplikazioei. Baimen horrekin, aplikazioek kontaktuen datuak ezaba ditzakete."</string> - <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Android TV gailuan gordetako kontaktuei buruzko datuak aldatzeko baimena ematen die aplikazioei. Baimen horrekin, aplikazioek kontaktuen datuak ezaba ditzakete."</string> - <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Telefonoan gordetako kontaktuei buruzko datuak aldatzeko baimena ematen die aplikazioei. Baimen horrekin, aplikazioek kontaktuen datuak ezaba ditzakete."</string> + <string name="permdesc_writeContacts" product="tablet" msgid="6422419281427826181">"Tabletan gordetako kontaktuei buruzko datuak aldatzeko baimena ematen dio aplikazioari. Baimen horrekin, aplikazioak kontaktuen datuak ezaba ditzake."</string> + <string name="permdesc_writeContacts" product="tv" msgid="6488872735379978935">"Android TV gailuan gordetako kontaktuei buruzko datuak aldatzeko baimena ematen dio aplikazioari. Baimen horrekin, aplikazioak kontaktuen datuak ezaba ditzake."</string> + <string name="permdesc_writeContacts" product="default" msgid="8304795696237065281">"Telefonoan gordetako kontaktuei buruzko datuak aldatzeko baimena ematen dio aplikazioari. Baimen horrekin, aplikazioak kontaktuen datuak ezaba ditzake."</string> <string name="permlab_readCallLog" msgid="1739990210293505948">"irakurri deien erregistroa"</string> <string name="permdesc_readCallLog" msgid="8964770895425873433">"Aplikazioak deien historia irakur dezake."</string> <string name="permlab_writeCallLog" msgid="670292975137658895">"idatzi deien erregistroan"</string> - <string name="permdesc_writeCallLog" product="tablet" msgid="2657525794731690397">"Tabletaren deien erregistroa aldatzeko baimena ematen die aplikazioei, sarrerako eta irteerako deiei buruzko datuak barne. Asmo txarreko aplikazioek deien erregistroa ezabatzeko edo aldatzeko erabil dezakete."</string> - <string name="permdesc_writeCallLog" product="tv" msgid="3934939195095317432">"Android TV gailuko deien erregistroa aldatzeko baimena ematen die aplikazioei, sarrerako eta irteerako deiei buruzko datuak barne. Baliteke asmo txarreko aplikazioek deien erregistroa ezabatzea edo aldatzea."</string> - <string name="permdesc_writeCallLog" product="default" msgid="5903033505665134802">"Telefonoaren deien erregistroa aldatzeko baimena ematen die aplikazioei, sarrerako eta irteerako deiei buruzko datuak barne. Asmo txarreko aplikazioek deien erregistroa ezabatzeko edo aldatzeko erabil dezakete."</string> + <string name="permdesc_writeCallLog" product="tablet" msgid="2657525794731690397">"Tabletaren deien erregistroa aldatzeko baimena ematen dio aplikazioari, sarrerako eta irteerako deiei buruzko datuak barne. Asmo txarreko aplikazioek deien erregistroa ezabatzeko edo aldatzeko erabil dezakete."</string> + <string name="permdesc_writeCallLog" product="tv" msgid="3934939195095317432">"Android TV gailuko deien erregistroa aldatzeko baimena ematen dio aplikazioari, sarrerako eta irteerako deiei buruzko datuak barne. Baliteke asmo txarreko aplikazioek deien erregistroa ezabatzea edo aldatzea."</string> + <string name="permdesc_writeCallLog" product="default" msgid="5903033505665134802">"Telefonoaren deien erregistroa aldatzeko baimena ematen dio aplikazioari, sarrerako eta irteerako deiei buruzko datuak barne. Asmo txarreko aplikazioek deien erregistroa ezabatzeko edo aldatzeko erabil dezakete."</string> <string name="permlab_bodySensors" msgid="662918578601619569">"Atzitu gorputz-sentsoreen datuak (esaterako, bihotz-maiztasuna) aplikazioa erabili bitartean"</string> - <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"Aplikazioak erabiltzen diren bitartean, gorputz-sentsoreen datuak (besteak beste, bihotz-maiztasuna, tenperatura eta odolean dagoen oxigenoaren ehunekoa) erabiltzeko baimena ematen die aplikazio horiei."</string> + <string name="permdesc_bodySensors" product="default" msgid="7652650410295512140">"Aplikazioa erabiltzen den bitartean, gorputz-sentsoreen datuak (besteak beste, bihotz-maiztasuna, tenperatura eta odolean dagoen oxigenoaren ehunekoa) erabiltzeko baimena ematen dio aplikazioari."</string> <string name="permlab_bodySensors_background" msgid="4912560779957760446">"Atzitu gorputz-sentsoreen datuak (adib., bihotz-maiztasunarenak) atzeko planoan"</string> - <string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"Aplikazioak atzeko planoan egon bitartean, gorputz-sentsoreen datuak (besteak beste, bihotz-maiztasuna, tenperatura eta odolean dagoen oxigenoaren ehunekoa) erabiltzeko baimena ematen die aplikazio horiei."</string> + <string name="permdesc_bodySensors_background" product="default" msgid="8870726027557749417">"Aplikazioa atzeko planoan egon bitartean, gorputz-sentsoreen datuak (besteak beste, bihotz-maiztasuna, tenperatura eta odolean dagoen oxigenoaren ehunekoa) erabiltzeko baimena ematen dio aplikazioari."</string> <string name="permlab_readCalendar" msgid="6408654259475396200">"irakurri egutegiko gertaerak eta xehetasunak"</string> <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"Aplikazioak tabletan gordetako egutegiko gertaerak irakur ditzake eta egutegiko datuak parteka eta gorde ditzake."</string> <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"Aplikazioak Android TV gailuan gordeta dituzun egutegiko gertaerak irakur ditzake, baita egutegiko datuak partekatu eta gorde ere."</string> @@ -479,7 +477,7 @@ <string name="permdesc_writeCalendar" product="tv" msgid="951246749004952706">"Android TV gailuan egutegiko gertaerak gehitzeko eta gehitutakoak kentzeko edo aldatzeko aukera dute aplikazioek. Gainera, egutegien jabeenak diruditen mezuak bidal ditzakete, edo gertaerak aldatu jabeei ezer esan gabe."</string> <string name="permdesc_writeCalendar" product="default" msgid="5416380074475634233">"Telefonoko gertaerak gehitzeko, kentzeko edo aldatzeko aukera du aplikazioak. Gainera, egutegien jabeenak diruditen mezuak bidal ditzake, eta gertaerak alda ditzake jabeei beraiei jakinarazi gabe."</string> <string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"atzitu kokapen-hornitzaileen komando gehigarriak"</string> - <string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Kokapen-hornitzailearen agindu gehigarriak erabiltzeko baimena ematen die aplikazioei. Horrela, agian aplikazioek GPSaren edo bestelako kokapenaren iturburuen funtzionamenduan eragina izan dezakete."</string> + <string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Kokapen-hornitzailearen agindu gehigarriak erabiltzeko baimena ematen dio aplikazioari. Horrela, agian aplikazioak GPSaren edo bestelako kokapenaren iturburuen funtzionamenduan eragina izan dezake."</string> <string name="permlab_accessFineLocation" msgid="6426318438195622966">"lortu kokapen zehatza aurreko planoan bakarrik"</string> <string name="permdesc_accessFineLocation" msgid="6732174080240016335">"Abian denean, aplikazioak kokapen zehatza lor dezake kokapen-zerbitzuen bidez. Aplikazioak kokapena lortu ahal izateko, kokapen-zerbitzuek aktibatuta egon behar dute gailuan. Agian bateria gehiago erabiliko du."</string> <string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"atzitu gutxi gorabeherako kokapena aurreko planoan bakarrik"</string> @@ -487,7 +485,7 @@ <string name="permlab_accessBackgroundLocation" msgid="1721164702777366138">"atzitu kokapena atzeko planoan"</string> <string name="permdesc_accessBackgroundLocation" msgid="8264885066095638105">"Aplikazioak kokapena atzi dezake, baita aplikazioa erabiltzen ari ez zarenean ere."</string> <string name="permlab_modifyAudioSettings" msgid="6129039778010031815">"aldatu audio-ezarpenak"</string> - <string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Audio-ezarpen orokorrak aldatzeko baimena ematen die aplikazioei; besteak beste, bolumena eta irteerarako zer bozgorailu erabiltzen den."</string> + <string name="permdesc_modifyAudioSettings" msgid="8687227609663124921">"Audio-ezarpen orokorrak aldatzeko baimena ematen dio aplikazioari; besteak beste, bolumena eta irteerarako zer bozgorailu erabiltzen den."</string> <string name="permlab_recordAudio" msgid="1208457423054219147">"grabatu audioa"</string> <string name="permdesc_recordAudio" msgid="5857246765327514062">"Aplikazioak abian den bitartean erabil dezake mikrofonoa audioa grabatzeko."</string> <string name="permlab_recordBackgroundAudio" msgid="5891032812308878254">"Audioa grabatu atzeko planoan."</string> @@ -495,7 +493,7 @@ <string name="permlab_detectScreenCapture" msgid="4447042362828799433">"hauteman pantaila-argazkiak aplikazioen leihoetan"</string> <string name="permdesc_detectScreenCapture" msgid="3485784917960342284">"Aplikazioa erabili bitartean pantaila-argazki bat ateratzen denean, jakinarazpen bat jasoko duzu aplikazioan."</string> <string name="permlab_sim_communication" msgid="176788115994050692">"bidali aginduak SIM txartelera"</string> - <string name="permdesc_sim_communication" msgid="4179799296415957960">"SIM txartelera aginduak bidaltzeko baimena ematen die aplikazioei. Oso arriskutsua da."</string> + <string name="permdesc_sim_communication" msgid="4179799296415957960">"SIM txartelera aginduak bidaltzeko baimena ematen dio aplikazioari. Oso arriskutsua da."</string> <string name="permlab_activityRecognition" msgid="1782303296053990884">"hauteman jarduera fisikoa"</string> <string name="permdesc_activityRecognition" msgid="8667484762991357519">"Aplikazioak jarduera fisikoa hauteman dezake."</string> <string name="permlab_camera" msgid="6320282492904119413">"atera argazkiak eta grabatu bideoak"</string> @@ -509,118 +507,118 @@ <string name="permlab_cameraHeadlessSystemUser" msgid="680194666834500050">"Eman interfaze grafikorik gabeko sistema-erabiltzaile gisa kamera erabiltzeko baimena aplikazio edo zerbitzu bati."</string> <string name="permdesc_cameraHeadlessSystemUser" msgid="6963163319710996412">"Aplikazio honek interfaze grafikorik gabeko sistema-erabiltzaile gisa erabil dezake kamera."</string> <string name="permlab_vibrate" msgid="8596800035791962017">"kontrolatu dardara"</string> - <string name="permdesc_vibrate" msgid="8733343234582083721">"Bibragailua kontrolatzeko baimena ematen die aplikazioei."</string> - <string name="permdesc_vibrator_state" msgid="7050024956594170724">"Dardara-egoera erabiltzeko baimena ematen die aplikazioei."</string> + <string name="permdesc_vibrate" msgid="8733343234582083721">"Bibragailua kontrolatzeko baimena ematen dio aplikazioari."</string> + <string name="permdesc_vibrator_state" msgid="7050024956594170724">"Dardara-egoera erabiltzeko baimena ematen dio aplikazioari."</string> <string name="permlab_callPhone" msgid="1798582257194643320">"deitu zuzenean telefono-zenbakietara"</string> - <string name="permdesc_callPhone" msgid="7892422187827695656">"Zuk ezer egin beharrik gabe, telefono-zenbakietara deitzeko baimena ematen die aplikazioei. Ondorioz, baliteke ustekabeko gastuak edo deiak eragitea. Kontuan izan aplikazioak ezingo duela deitu larrialdietarako zenbakietara. Zuk berretsi gabeko deiak eginda, asmo txarreko aplikazioek baimen hori erabil dezakete gastuak eragiteko edo operadore-kode jakin batzuk markatzeko, sarrerako deiak beste zenbaki batera automatikoki desbideratzeko asmoarekin."</string> + <string name="permdesc_callPhone" msgid="7892422187827695656">"Zuk ezer egin beharrik gabe, telefono-zenbakietara deitzeko baimena ematen dio aplikazioari. Ondorioz, baliteke ustekabeko gastuak edo deiak eragitea. Kontuan izan aplikazioak ezingo duela deitu larrialdietarako zenbakietara. Zuk berretsi gabeko deiak eginda, asmo txarreko aplikazioek baimen hori erabil dezakete gastuak eragiteko edo operadore-kode jakin batzuk markatzeko, sarrerako deiak beste zenbaki batera automatikoki desbideratzeko asmoarekin."</string> <string name="permlab_accessImsCallService" msgid="442192920714863782">"atzitu IMS dei-zerbitzua"</string> - <string name="permdesc_accessImsCallService" msgid="6328551241649687162">"Zuk ezer egin beharrik gabe deiak egiteko IMS zerbitzua erabiltzeko baimena ematen die aplikazioei."</string> + <string name="permdesc_accessImsCallService" msgid="6328551241649687162">"Zuk ezer egin beharrik gabe deiak egiteko IMS zerbitzua erabiltzeko baimena ematen dio aplikazioari."</string> <string name="permlab_readPhoneState" msgid="8138526903259297969">"irakurri telefonoaren egoera eta identitatea"</string> - <string name="permdesc_readPhoneState" msgid="7229063553502788058">"Gailuaren telefono-eginbideak erabiltzeko baimena ematen die aplikazioei. Baimen horrek aplikazioari telefono-zenbakia eta gailu IDak zein diren, deirik aktibo dagoen eta deia zer zenbakirekin konektatuta dagoen zehazteko baimena ematen die aplikazioei."</string> + <string name="permdesc_readPhoneState" msgid="7229063553502788058">"Gailuaren telefono-eginbideak erabiltzeko baimena ematen dio aplikazioari. Baimen horrek aplikazioari telefono-zenbakia eta gailu IDak zein diren, deirik aktibo dagoen eta deia zer zenbakirekin konektatuta dagoen zehazteko baimena ematen dio aplikazioari."</string> <string name="permlab_readBasicPhoneState" msgid="3214853233263871347">"irakurri oinarrizko egoera telefonikoa eta identitatea"</string> <string name="permdesc_readBasicPhoneState" msgid="828185691675460520">"Gailuaren oinarrizko eginbide telefonikoak erabiltzeko baimena ematen dio aplikazioari."</string> <string name="permlab_manageOwnCalls" msgid="9033349060307561370">"bideratu deiak sistemaren bidez"</string> - <string name="permdesc_manageOwnCalls" msgid="4431178362202142574">"Deiak sistemaren bidez bideratzea baimentzen die aplikazioei, deien zerbitzua ahal bezain ona izan dadin."</string> + <string name="permdesc_manageOwnCalls" msgid="4431178362202142574">"Deiak sistemaren bidez bideratzeko baimena ematen dio aplikazioari, deien zerbitzua ahal bezain ona izan dadin."</string> <string name="permlab_callCompanionApp" msgid="3654373653014126884">"ikusi eta kontrolatu deiak sistemaren bidez."</string> - <string name="permdesc_callCompanionApp" msgid="8474168926184156261">"Gailuan abian diren deiak eta deion informazioa ikusi eta kontrolatzeko baimena ematen die aplikazioei; besteak beste, deien zenbakiak eta deien egoera."</string> + <string name="permdesc_callCompanionApp" msgid="8474168926184156261">"Gailuan abian diren deiak eta deion informazioa ikusi eta kontrolatzeko baimena ematen dio aplikazioari; besteak beste, deien zenbakiak eta deien egoera."</string> <string name="permlab_exemptFromAudioRecordRestrictions" msgid="1164725468350759486">"salbuetsi audioa grabatzeko murriztapenen aurrean"</string> <string name="permdesc_exemptFromAudioRecordRestrictions" msgid="2425117015896871976">"Salbuetsi aplikazioa audioa grabatzeko murriztapenen aurrean."</string> <string name="permlab_acceptHandover" msgid="2925523073573116523">"jarraitu beste aplikazio batean hasitako deia"</string> - <string name="permdesc_acceptHandovers" msgid="7129026180128626870">"Beste aplikazio batean hasitako dei batekin jarraitzeko baimena ematen die aplikazioei."</string> + <string name="permdesc_acceptHandovers" msgid="7129026180128626870">"Beste aplikazio batean hasitako dei batekin jarraitzeko baimena ematen dio aplikazioari."</string> <string name="permlab_readPhoneNumbers" msgid="5668704794723365628">"irakurri telefono-zenbakiak"</string> - <string name="permdesc_readPhoneNumbers" msgid="7368652482818338871">"Gailuaren telefono-zenbakiak erabiltzeko baimena ematen die aplikazioei."</string> + <string name="permdesc_readPhoneNumbers" msgid="7368652482818338871">"Gailuaren telefono-zenbakiak erabiltzeko baimena ematen dio aplikazioari."</string> <string name="permlab_wakeLock" product="automotive" msgid="1904736682319375676">"mantendu piztuta autoko pantaila"</string> <string name="permlab_wakeLock" product="tablet" msgid="1527660973931694000">"eragotzi tableta inaktibo ezartzea"</string> <string name="permlab_wakeLock" product="tv" msgid="2856941418123343518">"Android TV gailua inaktibo ezar dadin eragotzi"</string> <string name="permlab_wakeLock" product="default" msgid="569409726861695115">"eragotzi telefonoa inaktibo ezartzea"</string> - <string name="permdesc_wakeLock" product="automotive" msgid="5995045369683254571">"Autoko pantaila piztuta mantentzeko baimena ematen die aplikazioei."</string> - <string name="permdesc_wakeLock" product="tablet" msgid="2441742939101526277">"Tableta inaktibo ezartzea galaraztea baimentzen die aplikazioei."</string> - <string name="permdesc_wakeLock" product="tv" msgid="2329298966735118796">"Android TV gailua inaktibo ezartzea eragozteko baimena ematen die aplikazioei."</string> - <string name="permdesc_wakeLock" product="default" msgid="3689523792074007163">"Telefonoa inaktibo ezartzea galaraztea baimentzen die aplikazioei."</string> + <string name="permdesc_wakeLock" product="automotive" msgid="5995045369683254571">"Autoko pantaila piztuta mantentzeko baimena ematen dio aplikazioari."</string> + <string name="permdesc_wakeLock" product="tablet" msgid="2441742939101526277">"Tableta inaktibo ezartzea galarazteko baimena ematen dio aplikazioari."</string> + <string name="permdesc_wakeLock" product="tv" msgid="2329298966735118796">"Android TV gailua inaktibo ezartzea eragozteko baimena ematen dio aplikazioari."</string> + <string name="permdesc_wakeLock" product="default" msgid="3689523792074007163">"Telefonoa inaktibo ezartzea galarazteko baimena ematen dio aplikazioari."</string> <string name="permlab_transmitIr" msgid="8077196086358004010">"transmititu infragorriak"</string> - <string name="permdesc_transmitIr" product="tablet" msgid="5884738958581810253">"Tabletaren infragorri-igorlea erabiltzeko baimena ematen die aplikazioei."</string> - <string name="permdesc_transmitIr" product="tv" msgid="3278506969529173281">"Android TV gailuaren infragorri-igorlea erabiltzeko baimena ematen die aplikazioei."</string> - <string name="permdesc_transmitIr" product="default" msgid="8484193849295581808">"Telefonoaren infragorri-igorlea erabiltzeko baimena ematen die aplikazioei."</string> + <string name="permdesc_transmitIr" product="tablet" msgid="5884738958581810253">"Tabletaren infragorri-igorlea erabiltzeko baimena ematen dio aplikazioari."</string> + <string name="permdesc_transmitIr" product="tv" msgid="3278506969529173281">"Android TV gailuaren infragorri-igorlea erabiltzeko baimena ematen dio aplikazioari."</string> + <string name="permdesc_transmitIr" product="default" msgid="8484193849295581808">"Telefonoaren infragorri-igorlea erabiltzeko baimena ematen dio aplikazioari."</string> <string name="permlab_setWallpaper" msgid="6959514622698794511">"ezarri horma-papera"</string> - <string name="permdesc_setWallpaper" msgid="2973996714129021397">"Sistemaren horma-papera aldatzeko baimena ematen die aplikazioei."</string> + <string name="permdesc_setWallpaper" msgid="2973996714129021397">"Sistemaren horma-papera aldatzeko baimena ematen dio aplikazioari."</string> <string name="permlab_setWallpaperHints" msgid="1153485176642032714">"doitu horma-paperaren tamaina"</string> - <string name="permdesc_setWallpaperHints" msgid="6257053376990044668">"Sistemaren horma-paperaren tamainaren doitzeak ezartzea baimentzen die aplikazioei."</string> + <string name="permdesc_setWallpaperHints" msgid="6257053376990044668">"Sistemaren horma-paperaren tamainaren doitzeak ezartzeko baimena ematen dio aplikazioari."</string> <string name="permlab_setTimeZone" msgid="7922618798611542432">"ezarri ordu-zona"</string> - <string name="permdesc_setTimeZone" product="tablet" msgid="1788868809638682503">"Tabletaren ordu-zona aldatzeko baimena ematen die aplikazioei."</string> - <string name="permdesc_setTimeZone" product="tv" msgid="9069045914174455938">"Android TV gailuaren ordu-zona aldatzeko baimena ematen die aplikazioei."</string> - <string name="permdesc_setTimeZone" product="default" msgid="4611828585759488256">"Telefonoaren ordu-zona aldatzeko baimena ematen die aplikazioei."</string> + <string name="permdesc_setTimeZone" product="tablet" msgid="1788868809638682503">"Tabletaren ordu-zona aldatzeko baimena ematen dio aplikazioari."</string> + <string name="permdesc_setTimeZone" product="tv" msgid="9069045914174455938">"Android TV gailuaren ordu-zona aldatzeko baimena ematen dio aplikazioari."</string> + <string name="permdesc_setTimeZone" product="default" msgid="4611828585759488256">"Telefonoaren ordu-zona aldatzeko baimena ematen dio aplikazioari."</string> <string name="permlab_getAccounts" msgid="5304317160463582791">"bilatu gailuko kontuak"</string> - <string name="permdesc_getAccounts" product="tablet" msgid="1784452755887604512">"Tabletak ezagutzen dituen kontuen zerrenda lortzeko baimena ematen die aplikazioei. Instalatuta dauzkazun aplikazioek sortutako kontuak har daitezke barnean."</string> - <string name="permdesc_getAccounts" product="tv" msgid="437604680436540822">"Android TV gailuak ezagutzen dituen kontuen zerrenda lortzeko baimena ematen die aplikazioei. Kontu horien artean, instalatuta dauzkazun aplikazioek sortutako kontuak egon litezke."</string> - <string name="permdesc_getAccounts" product="default" msgid="2491273043569751867">"Telefonoak ezagutzen dituen kontuen zerrenda lortzeko baimena ematen die aplikazioei. Instalatuta dauzkazun aplikazioek sortutako kontuak har daitezke barnean."</string> + <string name="permdesc_getAccounts" product="tablet" msgid="1784452755887604512">"Tabletak ezagutzen dituen kontuen zerrenda lortzeko baimena ematen dio aplikazioari. Instalatuta dauzkazun aplikazioek sortutako kontuak har daitezke barnean."</string> + <string name="permdesc_getAccounts" product="tv" msgid="437604680436540822">"Android TV gailuak ezagutzen dituen kontuen zerrenda lortzeko baimena ematen dio aplikazioari. Kontu horien artean, instalatuta dauzkazun aplikazioek sortutako kontuak egon litezke."</string> + <string name="permdesc_getAccounts" product="default" msgid="2491273043569751867">"Telefonoak ezagutzen dituen kontuen zerrenda lortzeko baimena ematen dio aplikazioari. Instalatuta dauzkazun aplikazioek sortutako kontuak har daitezke barnean."</string> <string name="permlab_accessNetworkState" msgid="2349126720783633918">"ikusi sareko konexioak"</string> - <string name="permdesc_accessNetworkState" msgid="4394564702881662849">"Sareko konexioei buruzko informazioa ikusteko baimena ematen die aplikazioei; adibidez, zer sare dauden eta zeintzuk dauden konektatuta."</string> + <string name="permdesc_accessNetworkState" msgid="4394564702881662849">"Sareko konexioei buruzko informazioa ikusteko baimena ematen dio aplikazioari; adibidez, zer sare dauden eta zeintzuk dauden konektatuta."</string> <string name="permlab_createNetworkSockets" msgid="3224420491603590541">"izan sarerako sarbide osoa"</string> - <string name="permdesc_createNetworkSockets" msgid="7722020828749535988">"Sare-socketak sortzeko eta sare-protokolo pertsonalizatuak erabiltzeko baimena ematen die aplikazioei. Arakatzaileak eta beste aplikazio batzuek Internetera konektatzeko moduak eskaintzen dituzte, beraz, baimen hori ez da beharrezkoa datuak Internetera bidaltzeko."</string> + <string name="permdesc_createNetworkSockets" msgid="7722020828749535988">"Sare-socketak sortzeko eta sare-protokolo pertsonalizatuak erabiltzeko baimena ematen dio aplikazioari. Arakatzaileak eta beste aplikazio batzuek Internetera konektatzeko moduak eskaintzen dituzte, beraz, baimen hori ez da beharrezkoa datuak Internetera bidaltzeko."</string> <string name="permlab_changeNetworkState" msgid="8945711637530425586">"aldatu sarearen konektagarritasuna"</string> - <string name="permdesc_changeNetworkState" msgid="649341947816898736">"Sarearen konexioaren egoera aldatzeko baimena ematen die aplikazioei."</string> + <string name="permdesc_changeNetworkState" msgid="649341947816898736">"Sarearen konexioaren egoera aldatzeko baimena ematen dio aplikazioari."</string> <string name="permlab_changeTetherState" msgid="9079611809931863861">"aldatu telefono bidezko konektagarritasuna"</string> - <string name="permdesc_changeTetherState" msgid="3025129606422533085">"Partekatutako Interneterako konexioaren egoera aldatzeko baimena ematen die aplikazioei."</string> + <string name="permdesc_changeTetherState" msgid="3025129606422533085">"Partekatutako Interneterako konexioaren egoera aldatzeko baimena ematen dio aplikazioari."</string> <string name="permlab_accessWifiState" msgid="5552488500317911052">"ikusi wifi-konexioak"</string> - <string name="permdesc_accessWifiState" msgid="6913641669259483363">"Wi-Fi sareei buruzko informazioa ikusteko baimena ematen die aplikazioei, adibidez, wifi-konexioa aktibatuta dagoen eta konektatutako Wi-Fi gailuen izenak zein diren."</string> + <string name="permdesc_accessWifiState" msgid="6913641669259483363">"Wifi-sareei buruzko informazioa ikusteko baimena ematen dio aplikazioari, adibidez, wifi-konexioa aktibatuta dagoen eta konektatutako wifi gailuen izenak zein diren."</string> <string name="permlab_changeWifiState" msgid="7947824109713181554">"konektatu wifira edo deskonektatu bertatik"</string> - <string name="permdesc_changeWifiState" msgid="7170350070554505384">"Wi-Fi sarbide-puntuetara konektatzeko edo haietatik deskonektatzeko baimena ematen die aplikazioei, baita Wi-Fi sareen gailu-konfigurazioari aldaketak egitekoa ere."</string> + <string name="permdesc_changeWifiState" msgid="7170350070554505384">"Wi-Fi sarbide-puntuetara konektatzeko edo haietatik deskonektatzeko baimena ematen dio aplikazioari, baita Wi-Fi sareen gailu-konfigurazioari aldaketak egitekoa ere."</string> <string name="permlab_changeWifiMulticastState" msgid="285626875870754696">"onartu Wi-Fi Multicast harrera"</string> - <string name="permdesc_changeWifiMulticastState" product="tablet" msgid="191079868596433554">"Wi-Fi sarearen bidez gailu guztiei bidalitako paketeak jasotzeko baimena ematen die aplikazioei multidifusio-helbideak erabilita, ez tableta soilik. Multidifusiokoa ez den moduak baino bateria gehiago erabiltzen du."</string> - <string name="permdesc_changeWifiMulticastState" product="tv" msgid="1336952358450652595">"Multidifusio-helbideak erabiliz wifi-sare bateko gailu guztiei (ez bakarrik Android TV gailuari) bidalitako paketeak jasotzeko baimena ematen die aplikazioei. Multidifusiokoa ez den moduak baino bateria gehiago erabiltzen du."</string> - <string name="permdesc_changeWifiMulticastState" product="default" msgid="8296627590220222740">"Wi-Fi sarearen bidez gailu guztiei bidalitako paketeak jasotzeko baimena ematen die aplikazioei multidifusio-helbideak erabilita, ez telefonoa soilik. Multidifusiokoa ez den moduak baino bateria gehiago erabiltzen du."</string> + <string name="permdesc_changeWifiMulticastState" product="tablet" msgid="191079868596433554">"Wifi sarearen bidez gailu guztiei bidalitako paketeak jasotzeko baimena ematen dio aplikazioari multidifusio-helbideak erabilita, ez tableta soilik. Multidifusiokoa ez den moduak baino bateria gehiago erabiltzen du."</string> + <string name="permdesc_changeWifiMulticastState" product="tv" msgid="1336952358450652595">"Multidifusio-helbideak erabiliz wifi-sare bateko gailu guztiei (ez bakarrik Android TV gailuari) bidalitako paketeak jasotzeko baimena ematen dio aplikazioari. Multidifusiokoa ez den moduak baino bateria gehiago erabiltzen du."</string> + <string name="permdesc_changeWifiMulticastState" product="default" msgid="8296627590220222740">"Wi-Fi sarearen bidez gailu guztiei bidalitako paketeak jasotzeko baimena ematen dio aplikazioari multidifusio-helbideak erabilita, ez telefonoa soilik. Multidifusiokoa ez den moduak baino bateria gehiago erabiltzen du."</string> <string name="permlab_bluetoothAdmin" msgid="6490373569441946064">"atzitu Bluetootharen ezarpenak"</string> - <string name="permdesc_bluetoothAdmin" product="tablet" msgid="5370837055438574863">"Tokiko Bluetooth tableta konfiguratzea eta urruneko gailuak detektatzea eta haiekin parekatzea baimentzen die aplikazioei."</string> - <string name="permdesc_bluetoothAdmin" product="tv" msgid="1623992984547014588">"Android TV gailuan Bluetootha konfiguratzeko eta urruneko gailuak hautemateko eta haiekin parekatzeko baimena ematen die aplikazioei."</string> - <string name="permdesc_bluetoothAdmin" product="default" msgid="7381341743021234863">"Tokiko Bluetooth telefonoa konfiguratzea eta urruneko gailuak detektatzea eta haiekin parekatzea baimentzen die aplikazioei."</string> + <string name="permdesc_bluetoothAdmin" product="tablet" msgid="5370837055438574863">"Tokiko Bluetooth tableta konfiguratzeko eta urruneko gailuak detektatzeko eta haiekin parekatzeko baimena ematen dio aplikazioari."</string> + <string name="permdesc_bluetoothAdmin" product="tv" msgid="1623992984547014588">"Android TV gailuan Bluetootha konfiguratzeko eta urruneko gailuak hautemateko eta haiekin parekatzeko baimena ematen dio aplikazioari."</string> + <string name="permdesc_bluetoothAdmin" product="default" msgid="7381341743021234863">"Tokiko Bluetooth telefonoa konfiguratzea eta urruneko gailuak detektatzeko eta haiekin parekatzeko baimena ematen dio aplikazioari."</string> <string name="permlab_accessWimaxState" msgid="7029563339012437434">"WiMAX sarera konektatzea eta deskonektatzea"</string> - <string name="permdesc_accessWimaxState" msgid="5372734776802067708">"WiMAX gaituta dagoen zehazteko eta konektatutako WiMAX sareei buruzko informazioa ikusteko baimena ematen die aplikazioei."</string> + <string name="permdesc_accessWimaxState" msgid="5372734776802067708">"WiMAX gaituta dagoen zehazteko eta konektatutako WiMAX sareei buruzko informazioa ikusteko baimena ematen dio aplikazioari."</string> <string name="permlab_changeWimaxState" msgid="6223305780806267462">"Aldatu WiMAX egoera"</string> - <string name="permdesc_changeWimaxState" product="tablet" msgid="4011097664859480108">"Tableta WiMAX sareetara konektatzeko edo haietatik deskonektatzeko baimena ematen die aplikazioei."</string> - <string name="permdesc_changeWimaxState" product="tv" msgid="5373274458799425276">"Android TV gailua WiMAX sareetara konektatzeko edo haietatik deskonektatzeko baimena ematen die aplikazioei."</string> - <string name="permdesc_changeWimaxState" product="default" msgid="1551666203780202101">"Telefonoa WiMAX sareetara konektatzeko edo haietatik deskonektatzeko baimena ematen die aplikazioei."</string> + <string name="permdesc_changeWimaxState" product="tablet" msgid="4011097664859480108">"Tableta WiMAX sareetara konektatzeko edo haietatik deskonektatzeko baimena ematen dio aplikazioari."</string> + <string name="permdesc_changeWimaxState" product="tv" msgid="5373274458799425276">"Android TV gailua WiMAX sareetara konektatzeko edo haietatik deskonektatzeko baimena ematen dio aplikazioari."</string> + <string name="permdesc_changeWimaxState" product="default" msgid="1551666203780202101">"Telefonoa WiMAX sareetara konektatzeko edo haietatik deskonektatzeko baimena ematen dio aplikazioari."</string> <string name="permlab_bluetooth" msgid="586333280736937209">"partekatu Bluetooth bidezko gailuekin"</string> - <string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Tabletaren Bluetooth konfigurazioa ikusteko eta parekatutako gailuekin konexioak egiteko eta onartzeko baimena ematen die aplikazioei."</string> - <string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Android TV gailuaren Bluetooth bidezko konexioaren konfigurazioa ikusteko eta parekatutako gailuekin konexioak sortzeko eta onartzeko baimena ematen die aplikazioei."</string> - <string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Telefonoaren Bluetooth konfigurazioa ikusteko eta parekatutako gailuekin konexioak egiteko eta onartzeko baimena ematen die aplikazioei."</string> + <string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"Tabletaren Bluetooth konfigurazioa ikusteko eta parekatutako gailuekin konexioak egiteko eta onartzeko baimena ematen dio aplikazioari."</string> + <string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"Android TV gailuaren Bluetooth bidezko konexioaren konfigurazioa ikusteko eta parekatutako gailuekin konexioak sortzeko eta onartzeko baimena ematen dio aplikazioari."</string> + <string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"Telefonoaren Bluetooth konfigurazioa ikusteko eta parekatutako gailuekin konexioak egiteko eta onartzeko baimena ematen dio aplikazioari."</string> <string name="permlab_bluetooth_scan" msgid="5402587142833124594">"inguruko Bluetooth bidezko gailuak hauteman eta haiekin parekatu"</string> - <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Inguruko Bluetooth bidezko gailuak hautemateko eta haiekin parekatzeko baimena ematen die aplikazioei"</string> + <string name="permdesc_bluetooth_scan" product="default" msgid="6540723536925289276">"Inguruko Bluetooth bidezko gailuak hautemateko eta haiekin parekatzeko baimena ematen dio aplikazioari"</string> <string name="permlab_bluetooth_connect" msgid="6657463246355003528">"parekatutako Bluetooth bidezko gailuetara konektatu"</string> - <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Parekatutako Bluetooth bidezko gailuetara konektatzeko baimena ematen die aplikazioei"</string> + <string name="permdesc_bluetooth_connect" product="default" msgid="4546016548795544617">"Parekatutako Bluetooth bidezko gailuetara konektatzeko baimena ematen dio aplikazioari"</string> <string name="permlab_bluetooth_advertise" msgid="2781147747928853177">"inguruko Bluetooth bidezko gailuetan informazioa iragarri"</string> - <string name="permdesc_bluetooth_advertise" product="default" msgid="6085174451034210183">"Inguruko Bluetooth bidezko gailuetan informazioa iragartzeko baimena ematen die aplikazioei"</string> + <string name="permdesc_bluetooth_advertise" product="default" msgid="6085174451034210183">"Inguruko Bluetooth bidezko gailuetan informazioa iragartzeko baimena ematen dio aplikazioari"</string> <string name="permlab_uwb_ranging" msgid="8141915781475770665">"banda ultrazabala darabilten inguruko gailuen arteko distantzia erlatiboa zehaztu"</string> <string name="permdesc_uwb_ranging" msgid="2519723069604307055">"Banda ultrazabala darabilten inguruko gailuen arteko distantzia erlatiboa zehazteko baimena ematen dio aplikazioari"</string> <string name="permlab_nearby_wifi_devices" msgid="392774237063608500">"inguruko wifi-gailuekin interakzioan jardun"</string> - <string name="permdesc_nearby_wifi_devices" msgid="3054307728646332906">"Inguruko wifi-gailuetan iragartzeko, haiekin konektatzeko eta haien kokapena zehazteko baimena ematen die aplikazioei"</string> + <string name="permdesc_nearby_wifi_devices" msgid="3054307728646332906">"Inguruko wifi-gailuetan iragartzeko, haiekin konektatzeko eta haien kokapena zehazteko baimena ematen dio aplikazioari"</string> <string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"NFC bidezko ordainketa-zerbitzu lehenetsiari buruzko informazioa"</string> - <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"NFC bidezko ordainketa-zerbitzu lehenetsiari buruzko informazioa jasotzeko baimena ematen die aplikazioei, hala nola erregistratutako laguntzaileak eta ibilbidearen helmuga."</string> + <string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"NFC bidezko ordainketa-zerbitzu lehenetsiari buruzko informazioa jasotzeko baimena ematen dio aplikazioari, hala nola erregistratutako laguntzaileak eta ibilbidearen helmuga."</string> <string name="permlab_nfc" msgid="1904455246837674977">"kontrolatu Near Field Communication komunikazioa"</string> - <string name="permdesc_nfc" msgid="8352737680695296741">"Near Field Communication (NFC) etiketekin, txartelekin eta irakurgailuekin komunikatzeko baimena ematen die aplikazioei."</string> + <string name="permdesc_nfc" msgid="8352737680695296741">"Near Field Communication (NFC) etiketekin, txartelekin eta irakurgailuekin komunikatzeko baimena ematen dio aplikazioari."</string> <string name="permlab_nfcTransactionEvent" msgid="5868209446710407679">"Elementu seguruetako transakzioen gertaerak"</string> <string name="permdesc_nfcTransactionEvent" msgid="1904286701876487397">"Elementu seguru batean egiten ari diren transakzioei buruzko informazioa jasotzeko baimena ematen dio aplikazioari."</string> <string name="permlab_disableKeyguard" msgid="3605253559020928505">"desgaitu pantailaren blokeoa"</string> - <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Teklen blokeoa eta erlazionatutako pasahitz-segurtasuna desgaitzeko baimena ematen die aplikazioei. Adibidez, telefonoak teklen blokeoa desgaitzen du telefono-deiak jasotzen dituenean, eta berriro gaitzen du deiak amaitzean."</string> + <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"Teklen blokeoa eta erlazionatutako pasahitz-segurtasuna desgaitzeko baimena ematen dio aplikazioari. Adibidez, telefonoak teklen blokeoa desgaitzen du telefono-deiak jasotzen dituenean, eta berriro gaitzen du deiak amaitzean."</string> <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"eskatu pantailaren blokeoa konplexua izatea"</string> - <string name="permdesc_requestPasswordComplexity" msgid="1130556896836258567">"Pantailaren blokeoaren konplexutasun-maila (handia, ertaina, txikia edo bat ere ez) jakiteko baimena ematen die aplikazioei. Informazio horrekin, pantailaren blokeoaren luzera-barruti edo mota posiblea ondoriozta liteke. Halaber, pantailaren blokeoa maila jakin batera igotzeko iradoki diezaiekete aplikazioek erabiltzaileei, baina horri ez ikusi egin eta aplikazioak erabiltzen jarraitzeko aukera dute erabiltzaileek. Kontuan izan pantailaren blokeoa ez dela gordetzen testu arrunt gisa; beraz, aplikazioek ez dute jakingo pasahitz zehatza zein den."</string> + <string name="permdesc_requestPasswordComplexity" msgid="1130556896836258567">"Pantailaren blokeoaren konplexutasun-maila (handia, ertaina, txikia edo bat ere ez) jakiteko baimena ematen dio aplikazioari. Informazio horrekin, pantailaren blokeoaren luzera-barruti edo mota posiblea ondoriozta liteke. Halaber, pantailaren blokeoa maila jakin batera igotzeko iradoki diezaiekete aplikazioek erabiltzaileei, baina horri ez ikusi egin eta aplikazioak erabiltzen jarraitzeko aukera dute erabiltzaileek. Kontuan izan pantailaren blokeoa ez dela gordetzen testu arrunt gisa; beraz, aplikazioek ez dute jakingo pasahitz zehatza zein den."</string> <string name="permlab_postNotification" msgid="4875401198597803658">"jakinarazpenak erakutsi"</string> - <string name="permdesc_postNotification" msgid="5974977162462877075">"Jakinarazpenak erakusteko baimena ematen die aplikazioei"</string> + <string name="permdesc_postNotification" msgid="5974977162462877075">"Jakinarazpenak erakusteko baimena ematen dio aplikazioari"</string> <string name="permlab_turnScreenOn" msgid="219344053664171492">"piztu pantaila"</string> <string name="permdesc_turnScreenOn" msgid="4394606875897601559">"Pantaila pizteko baimena ematen dio aplikazioari."</string> <string name="permlab_useBiometric" msgid="6314741124749633786">"erabili hardware biometrikoa"</string> - <string name="permdesc_useBiometric" msgid="7502858732677143410">"Autentifikatzeko hardware biometrikoa erabiltzeko baimena ematen die aplikazioei."</string> + <string name="permdesc_useBiometric" msgid="7502858732677143410">"Autentifikatzeko hardware biometrikoa erabiltzeko baimena ematen dio aplikazioari."</string> <string name="permlab_manageFingerprint" msgid="7432667156322821178">"kudeatu hatz-marken hardwarea"</string> - <string name="permdesc_manageFingerprint" msgid="2025616816437339865">"Aztarna digitalaren txantiloiak gehitzeko eta ezabatzeko metodoei dei egitea baimentzen die aplikazioei."</string> + <string name="permdesc_manageFingerprint" msgid="2025616816437339865">"Aztarna digitalaren txantiloiak gehitzeko eta ezabatzeko metodoei dei egiteko baimena ematen dio aplikazioari."</string> <string name="permlab_useFingerprint" msgid="1001421069766751922">"erabili hatz-marken hardwarea"</string> - <string name="permdesc_useFingerprint" msgid="412463055059323742">"Autentifikatzeko hatz-marken hardwarea erabiltzeko baimena ematen die aplikazioei."</string> + <string name="permdesc_useFingerprint" msgid="412463055059323742">"Autentifikatzeko hatz-marken hardwarea erabiltzeko baimena ematen dio aplikazioari."</string> <string name="permlab_audioWrite" msgid="8501705294265669405">"musika bilduma aldatu"</string> - <string name="permdesc_audioWrite" msgid="8057399517013412431">"Musika bilduma aldatzeko baimena ematen die aplikazioei."</string> + <string name="permdesc_audioWrite" msgid="8057399517013412431">"Musika bilduma aldatzeko baimena ematen dio aplikazioari."</string> <string name="permlab_videoWrite" msgid="5940738769586451318">"bideo bilduma aldatu"</string> - <string name="permdesc_videoWrite" msgid="6124731210613317051">"Bideo bilduma aldatzeko baimena ematen die aplikazioei."</string> + <string name="permdesc_videoWrite" msgid="6124731210613317051">"Bideo bilduma aldatzeko baimena ematen dio aplikazioari."</string> <string name="permlab_imagesWrite" msgid="1774555086984985578">"argazki bilduma aldatu"</string> - <string name="permdesc_imagesWrite" msgid="5195054463269193317">"Argazki bilduma aldatzeko baimena ematen die aplikazioei."</string> + <string name="permdesc_imagesWrite" msgid="5195054463269193317">"Argazki bilduma aldatzeko baimena ematen dio aplikazioari."</string> <string name="permlab_mediaLocation" msgid="7368098373378598066">"multimedia-edukien bildumako kokapena irakurri"</string> - <string name="permdesc_mediaLocation" msgid="597912899423578138">"Multimedia-edukien bildumako kokapena irakurtzeko baimena ematen die aplikazioei."</string> + <string name="permdesc_mediaLocation" msgid="597912899423578138">"Multimedia-edukien bildumako kokapena irakurtzeko baimena ematen dio aplikazioari."</string> <string name="biometric_app_setting_name" msgid="3339209978734534457">"Erabili sistema biometrikoak"</string> <string name="biometric_or_screen_lock_app_setting_name" msgid="5348462421758257752">"Erabili sistema biometrikoak edo pantailaren blokeoa"</string> <string name="biometric_dialog_default_title" msgid="55026799173208210">"Egiaztatu zeu zarela"</string> @@ -636,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Erabili pantailaren blokeoa"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Aurrera egiteko, desblokeatu pantailaren blokeoa"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Sakatu irmo sentsorea"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Ez da ezagutu hatz-marka. Saiatu berriro."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Garbitu hatz-marken sentsorea eta saiatu berriro"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Garbitu sentsorea eta saiatu berriro"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Sakatu irmo sentsorea"</string> @@ -701,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"Ezin da hauteman aurpegia. Eutsi telefonoari begien parean."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Mugimendu gehiegi dago. Eutsi tinko telefonoari."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Erregistratu berriro aurpegia."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"Ez da ezagutu aurpegia. Saiatu berriro."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Aldatu buruaren posizioa apur bat"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Begiratu zuzenago telefonoari"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Begiratu zuzenago telefonoari"</string> @@ -740,45 +736,45 @@ <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Arazo bat izan da. Saiatu berriro."</string> <string name="face_icon_content_description" msgid="465030547475916280">"Aurpegiaren ikonoa"</string> <string name="permlab_readSyncSettings" msgid="6250532864893156277">"irakurri sinkronizazio-ezarpenak"</string> - <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Kontu baten sinkronizazio-ezarpenak irakurtzeko baimena ematen die aplikazioei. Adibidez, Jendea aplikazioa konturen batekin sinkronizatuta dagoen zehatz dezake."</string> + <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Kontu baten sinkronizazio-ezarpenak irakurtzeko baimena ematen dio aplikazioari. Adibidez, Jendea aplikazioa konturen batekin sinkronizatuta dagoen zehatz dezake."</string> <string name="permlab_writeSyncSettings" msgid="6583154300780427399">"aktibatu eta desaktibatu sinkronizazioa"</string> <string name="permdesc_writeSyncSettings" msgid="6029151549667182687">"Kontu baten sinkronizazio-ezarpenak aldatzeko baimena ematen die aplikazioei. Adibidez, Jendea aplikazioa kontu batekin sinkronizatzeko erabil daiteke."</string> <string name="permlab_readSyncStats" msgid="3747407238320105332">"irakurri sinkronizazio-estatistikak"</string> <string name="permdesc_readSyncStats" msgid="3867809926567379434">"Kontu baten sinkronizazio-estatistikak irakurtzeko baimena ematen dio; besteak beste, sinkronizazio-gertaeren historia eta sinkronizatutako datu kopurua."</string> <string name="permlab_sdcardRead" msgid="5791467020950064920">"Irakurri biltegi partekatuko edukia"</string> - <string name="permdesc_sdcardRead" msgid="6872973242228240382">"Biltegi partekatuko edukia irakurtzeko baimena ematen die aplikazioei."</string> + <string name="permdesc_sdcardRead" msgid="6872973242228240382">"Biltegi partekatuko edukia irakurtzeko baimena ematen dio aplikazioari."</string> <string name="permlab_readMediaAudio" msgid="8723513075731763810">"irakurri biltegi partekatuko audio-fitxategiak"</string> - <string name="permdesc_readMediaAudio" msgid="5299772574434619399">"Biltegi partekatuko audio-fitxategiak irakurtzeko baimena ematen die aplikazioei."</string> + <string name="permdesc_readMediaAudio" msgid="5299772574434619399">"Biltegi partekatuko audio-fitxategiak irakurtzeko baimena ematen dio aplikazioari."</string> <string name="permlab_readMediaVideo" msgid="7768003311260655007">"irakurri biltegi partekatuko bideo-fitxategiak"</string> - <string name="permdesc_readMediaVideo" msgid="3846400073770403528">"Biltegi partekatuko bideo-fitxategiak irakurtzeko baimena ematen die aplikazioei."</string> + <string name="permdesc_readMediaVideo" msgid="3846400073770403528">"Biltegi partekatuko bideo-fitxategiak irakurtzeko baimena ematen dio aplikazioari."</string> <string name="permlab_readMediaImages" msgid="4057590631020986789">"irakurri biltegi partekatuko irudi-fitxategiak"</string> - <string name="permdesc_readMediaImages" msgid="5836219373138469259">"Biltegi partekatuko irudi-fitxategiak irakurtzeko baimena ematen die aplikazioei."</string> + <string name="permdesc_readMediaImages" msgid="5836219373138469259">"Biltegi partekatuko irudi-fitxategiak irakurtzeko baimena ematen dio aplikazioari."</string> <string name="permlab_readVisualUserSelect" msgid="5516204215354667586">"irakurri biltegi partekatuko irudi- eta bideo-fitxategiak"</string> - <string name="permdesc_readVisualUserSelect" msgid="8027174717714968217">"Biltegi partekatuko irudi- eta bideo-fitxategiak irakurtzeko baimena ematen die aplikazioei."</string> + <string name="permdesc_readVisualUserSelect" msgid="8027174717714968217">"Biltegi partekatuko irudi- eta bideo-fitxategiak irakurtzeko baimena ematen dio aplikazioari."</string> <string name="permlab_sdcardWrite" msgid="4863021819671416668">"aldatu edo ezabatu biltegi partekatuko edukia"</string> - <string name="permdesc_sdcardWrite" msgid="8376047679331387102">"Biltegi partekatuko edukian idazteko baimena ematen die aplikazioei."</string> + <string name="permdesc_sdcardWrite" msgid="8376047679331387102">"Biltegi partekatuko edukian idazteko baimena ematen dio aplikazioari."</string> <string name="permlab_use_sip" msgid="8250774565189337477">"egin/jaso SIP deiak"</string> - <string name="permdesc_use_sip" msgid="3590270893253204451">"SIP deiak egitea eta jasotzeko baimena ematen die aplikazioei."</string> + <string name="permdesc_use_sip" msgid="3590270893253204451">"SIP deiak egiteko eta jasotzeko baimena ematen dio aplikazioari."</string> <string name="permlab_register_sim_subscription" msgid="1653054249287576161">"erregistratu telekomunikabideekiko SIM konexio berriak"</string> - <string name="permdesc_register_sim_subscription" msgid="4183858662792232464">"Telekomunikabideekiko SIM konexio berriak erregistratzea baimentzen die aplikazioei."</string> + <string name="permdesc_register_sim_subscription" msgid="4183858662792232464">"Telekomunikabideekiko SIM konexio berriak erregistratzeko baimena ematen dio aplikazioari."</string> <string name="permlab_register_call_provider" msgid="6135073566140050702">"erregistratu telekomunikabideekiko konexio berriak"</string> - <string name="permdesc_register_call_provider" msgid="4201429251459068613">"Telekomunikabideekiko konexio berriak erregistratzea baimentzen die aplikazioei."</string> + <string name="permdesc_register_call_provider" msgid="4201429251459068613">"Telekomunikabideekiko konexio berriak erregistratzeko baimena ematen dio aplikazioari."</string> <string name="permlab_connection_manager" msgid="3179365584691166915">"kudeatu telekomunikabideekiko konexioak"</string> - <string name="permdesc_connection_manager" msgid="1426093604238937733">"Telekomunikabideekiko konexioak kudeatzea baimentzen die aplikazioei."</string> + <string name="permdesc_connection_manager" msgid="1426093604238937733">"Telekomunikabideekiko konexioak kudeatzeko baimena ematen dio aplikazioari."</string> <string name="permlab_bind_incall_service" msgid="5990625112603493016">"erabili pantaila deiak abian direnean"</string> - <string name="permdesc_bind_incall_service" msgid="4124917526967765162">"Erabiltzaileak deiaren pantaila noiz eta nola ikusten duen kontrolatzeko baimena ematen die aplikazioei."</string> + <string name="permdesc_bind_incall_service" msgid="4124917526967765162">"Erabiltzaileak deiaren pantaila noiz eta nola ikusten duen kontrolatzeko baimena ematen dio aplikazioari."</string> <string name="permlab_bind_connection_service" msgid="5409268245525024736">"jardun interakzioan telefono-zerbitzuekin"</string> - <string name="permdesc_bind_connection_service" msgid="6261796725253264518">"Deiak egiteko eta jasotzeko telefonia-zerbitzuekin interakzioan aritzeko baimena ematen die aplikazioei."</string> + <string name="permdesc_bind_connection_service" msgid="6261796725253264518">"Deiak egiteko eta jasotzeko telefonia-zerbitzuekin interakzioan aritzeko baimena ematen dio aplikazioari."</string> <string name="permlab_control_incall_experience" msgid="6436863486094352987">"eskaini erabiltzaileentzako aukerak deiak abian direnean"</string> - <string name="permdesc_control_incall_experience" msgid="5896723643771737534">"Deiak abian direnean erabiltzeko aukera eskaintzea baimentzen die aplikazioei."</string> + <string name="permdesc_control_incall_experience" msgid="5896723643771737534">"Deiak abian direnean erabiltzeko aukera eskaintzeko baimena ematen dio aplikazioari."</string> <string name="permlab_readNetworkUsageHistory" msgid="8470402862501573795">"irakurri sare-erabileraren historia"</string> - <string name="permdesc_readNetworkUsageHistory" msgid="1112962304941637102">"Sare eta aplikazio jakin batzuen sare-erabileraren historia irakurtzeko baimena ematen die aplikazioei."</string> + <string name="permdesc_readNetworkUsageHistory" msgid="1112962304941637102">"Sare eta aplikazio jakin batzuen sare-erabileraren historia irakurtzeko baimena ematen dio aplikazioari."</string> <string name="permlab_manageNetworkPolicy" msgid="6872549423152175378">"kudeatu sare-gidalerroak"</string> - <string name="permdesc_manageNetworkPolicy" msgid="1865663268764673296">"Sareko gidalerroak kudeatzea eta aplikazioetarako berariazko arauak definitzea baimentzen die aplikazioei."</string> + <string name="permdesc_manageNetworkPolicy" msgid="1865663268764673296">"Sareko gidalerroak kudeatzeko eta aplikazioetarako berariazko arauak definitzeko baimena ematen dio aplikazioari."</string> <string name="permlab_modifyNetworkAccounting" msgid="7448790834938749041">"aldatu sare-erabileraren kalkuluak"</string> - <string name="permdesc_modifyNetworkAccounting" msgid="5076042642247205390">"Aplikazioen sare-erabilera kalkulatzeko modua aldatzeko baimena ematen die aplikazioei. Aplikazio normalek ez lukete beharko."</string> + <string name="permdesc_modifyNetworkAccounting" msgid="5076042642247205390">"Aplikazioen sare-erabilera kalkulatzeko modua aldatzeko baimena ematen dio aplikazioari. Aplikazio normalek ez lukete beharko."</string> <string name="permlab_accessNotifications" msgid="7130360248191984741">"atzitu jakinarazpenak"</string> - <string name="permdesc_accessNotifications" msgid="761730149268789668">"Jakinarazpenak berreskuratu, aztertu eta garbitzeko baimena ematen die aplikazioei, beste aplikazioek argitaratutako jakinarazpenak barne."</string> + <string name="permdesc_accessNotifications" msgid="761730149268789668">"Jakinarazpenak berreskuratu, aztertu eta garbitzeko baimena ematen dio aplikazioari, beste aplikazioek argitaratutako jakinarazpenak barne."</string> <string name="permlab_bindNotificationListenerService" msgid="5848096702733262458">"lotu jakinarazpen-hautemaile bati"</string> <string name="permdesc_bindNotificationListenerService" msgid="4970553694467137126">"Jakinarazpen-hautemaile baten goi-mailako interfazera lotzeko aukera ematen dio titularrari. Aplikazio normalek ez dute baimen hau behar."</string> <string name="permlab_bindConditionProviderService" msgid="5245421224814878483">"lotu baldintza-hornitzaileen zerbitzuei"</string> @@ -790,7 +786,7 @@ <string name="permlab_accessNetworkConditions" msgid="1270732533356286514">"hauteman sarearen baldintzei buruzko behaketak"</string> <string name="permdesc_accessNetworkConditions" msgid="2959269186741956109">"Sareko baldintzak hautemateko aukera ematen die aplikazioei. Aplikazio normalek ez dute baimen hau behar."</string> <string name="permlab_setInputCalibration" msgid="932069700285223434">"Aldatu idazteko gailuaren kalibrazioa"</string> - <string name="permdesc_setInputCalibration" msgid="2937872391426631726">"Ukipen-pantailaren kalibrazio-parametroak aldatzeko baimena ematen die aplikazioei. Aplikazio normalek ez lukete beharko."</string> + <string name="permdesc_setInputCalibration" msgid="2937872391426631726">"Ukipen-pantailaren kalibrazio-parametroak aldatzeko baimena ematen dio aplikazioari. Aplikazio normalek ez lukete beharko."</string> <string name="permlab_accessDrmCertificates" msgid="6473765454472436597">"atzitu DRM ziurtagiriak"</string> <string name="permdesc_accessDrmCertificates" msgid="6983139753493781941">"DRM ziurtagiriak hornitzea eta erabiltzeko baimena ematen die aplikazioei. Aplikazio normalek ez lukete beharko."</string> <string name="permlab_handoverStatus" msgid="7620438488137057281">"Jaso Android Beam transferentzien egoera"</string> @@ -802,7 +798,7 @@ <string name="permlab_bindCarrierServices" msgid="2395596978626237474">"lotu operadorearen zerbitzuei"</string> <string name="permdesc_bindCarrierServices" msgid="9185614481967262900">"Operadorearen zerbitzuei lotzea baimentzen die titularrei. Aplikazio normalek ez dute baimen hau behar."</string> <string name="permlab_access_notification_policy" msgid="5524112842876975537">"atzitu ez molestatzeko modua"</string> - <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Ez molestatzeko moduaren konfigurazioa irakurtzeko eta bertan idazteko baimena ematen die aplikazioei."</string> + <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Ez molestatzeko moduaren konfigurazioa irakurtzeko eta bertan idazteko baimena ematen dio aplikazioari."</string> <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"hasi ikusteko baimena erabiltzen"</string> <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Aplikazioaren baimena erabiltzen hasteko baimena ematen die titularrei. Aplikazio normalek ez lukete beharko."</string> <string name="permlab_startReviewPermissionDecisions" msgid="8690578688476599284">"hasi baimenen inguruko erabakiak ikusten"</string> @@ -810,7 +806,7 @@ <string name="permlab_startViewAppFeatures" msgid="7955084203185903001">"hasi aplikazioaren eginbideak ikusten"</string> <string name="permdesc_startViewAppFeatures" msgid="7207240860165206107">"Aplikazio baten eginbideei buruzko informazioa ikusten hasteko baimena ematen die titularrei."</string> <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"atzitu sentsoreen datuen laginak abiadura handian"</string> - <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Aplikazioak 200 Hz-tik gorako abiaduran hartu ahal izango ditu sentsoreen datuen laginak"</string> + <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"200 Hz-tik gorako abiaduran sentsoreen datuen laginak hartzeko baimena ematen dio aplikazioari"</string> <string name="permlab_updatePackagesWithoutUserAction" msgid="3363272609642618551">"eguneratu aplikazioa erabiltzaileak ezer egin gabe"</string> <string name="permdesc_updatePackagesWithoutUserAction" msgid="4567739631260526366">"Lehendik instalatu duen aplikazioa erabiltzaileak ezer egin gabe eguneratzeko baimena ematen dio titularrari"</string> <string name="policylab_limitPassword" msgid="4851829918814422199">"Ezarri pasahitzen arauak"</string> @@ -1080,9 +1076,9 @@ <string name="js_dialog_before_unload" msgid="7213364985774778744">"<xliff:g id="MESSAGE">%s</xliff:g>\n\nZiur orritik irten nahi duzula?"</string> <string name="autofill_window_title" msgid="4379134104008111961">"Bete automatikoki <xliff:g id="SERVICENAME">%1$s</xliff:g> erabiliz"</string> <string name="permlab_setAlarm" msgid="1158001610254173567">"ezarri alarmak"</string> - <string name="permdesc_setAlarm" msgid="2185033720060109640">"Instalatutako alarma batean alarmak ezartzea baimentzen die aplikazioei. Alarma-aplikazio batzuek agian ez dute eginbide hori inplementatuko."</string> + <string name="permdesc_setAlarm" msgid="2185033720060109640">"Instalatutako alarma batean alarmak ezartzeko baimena ematen dio aplikazioari. Alarma-aplikazio batzuek agian ez dute eginbide hori inplementatuko."</string> <string name="permlab_addVoicemail" msgid="4770245808840814471">"gehitu erantzungailua"</string> - <string name="permdesc_addVoicemail" msgid="5470312139820074324">"Erantzungailuko sarrera-ontzian mezuak gehitzeko baimena ematen die aplikazioei."</string> + <string name="permdesc_addVoicemail" msgid="5470312139820074324">"Erantzungailuko sarrera-ontzian mezuak gehitzeko baimena ematen dio aplikazioari."</string> <string name="pasted_from_clipboard" msgid="7355790625710831847">"<xliff:g id="PASTING_APP_NAME">%1$s</xliff:g> aplikazioak arbeleko edukia itsatsi du"</string> <string name="more_item_label" msgid="7419249600215749115">"Gehiago"</string> <string name="prepend_shortcut_label" msgid="1743716737502867951">"Menua+"</string> diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml index c661e95de9c7..6cdaf78a0e82 100644 --- a/core/res/res/values-fa/strings.xml +++ b/core/res/res/values-fa/strings.xml @@ -434,10 +434,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"به برنامه اجازه میدهد از سرویسهای پیشنما از نوع «معافیت سیستم» استفاده کند"</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"اجرای سرویس پیشنما از نوع «fileManagement»"</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"به برنامه اجازه میدهد از سرویسهای پیشنما از نوع «fileManagement» استفاده کند"</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"اجرای سرویس پیشزمینهای از نوع «mediaProcessing»"</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"به برنامه اجازه میدهد از سرویسهای پیشزمینهای از نوع «mediaProcessing» استفاده کند"</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"اجرای سرویس پیشنما از نوع «استفاده ویژه»"</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"به برنامه اجازه میدهد از سرویسهای پیشنما از نوع «استفاده ویژه» استفاده کند"</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"اندازهگیری اندازه فضای ذخیرهسازی برنامه"</string> @@ -636,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"از قفل صفحه استفاده کنید"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"برای ادامه، قفل صفحهتان را وارد کنید"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"محکم روی حسگر فشار دهید"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"اثر انگشت شناسایی نشد. دوباره امتحان کنید."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"حسگر اثر انگشت را تمیز و دوباره امتحان کنید"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"حسگر را تمیز و دوباره امتحان کنید"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"محکم روی حسگر فشار دهید"</string> @@ -701,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"چهره دیده نمیشود. تلفن را همسطح چشمانتان نگه دارید."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"حرکت خیلی زیاد است. تلفن را ثابت نگهدارید."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"لطفاً چهرهتان را مجدداً ثبت کنید."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"چهره شناسایی نشد. دوباره امتحان کنید."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"موقعیت سرتان را کمی تغییر دهید"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"مستقیمتر به تلفن نگاه کنید"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"مستقیمتر به تلفن نگاه کنید"</string> diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml index 9aad9fa6b15e..e0dd50d6198a 100644 --- a/core/res/res/values-fi/strings.xml +++ b/core/res/res/values-fi/strings.xml @@ -434,10 +434,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Sallii sovelluksen käyttää etualan palveluja, joiden tyyppi on \"systemExempted\""</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"käyttää etualan palveluja, joiden tyyppi on \"fileManagement\""</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"Sallii sovelluksen käyttää etualan palveluja, joiden tyyppi on \"fileManagement\""</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"käyttää etualan palveluja, joiden tyyppi on \"mediaProcessing\""</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"Sallii sovelluksen käyttää etualan palveluja, joiden tyyppi on \"mediaProcessing\""</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"käyttää etualan palveluja, joiden tyyppi on \"specialUse\""</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Sallii sovelluksen käyttää etualan palveluja, joiden tyyppi on \"specialUse\""</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"sovellusten tallennustilan mittaaminen"</string> @@ -636,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Käytä näytön lukitusta"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Jatka lisäämällä näytön lukituksen avaustapa"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Paina anturia voimakkaasti"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Sormenjälkeä ei tunnistettu. Yritä uudelleen."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Puhdista sormenjälkitunnistin ja yritä uudelleen"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Puhdista anturi ja yritä uudelleen"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Paina tunnistinta voimakkaasti"</string> @@ -701,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"Kasvoja ei näy. Pidä puhelinta silmien korkeudella."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Laite liikkui liikaa. Pidä puhelin vakaana."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Rekisteröi kasvot uudelleen."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"Kasvoja ei tunnistettu. Yritä uudelleen."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Liikuta päätä hieman"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Katso suoremmin puhelimeen"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Katso suoremmin puhelimeen"</string> diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml index 7be3041cdc5f..0bb9ee5bcb50 100644 --- a/core/res/res/values-fr-rCA/strings.xml +++ b/core/res/res/values-fr-rCA/strings.xml @@ -435,10 +435,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Autoriser l\'application à utiliser les services d\'avant-plan avec le type « système exempté »"</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"exécuter le service d\'avant-plan avec le type « fileManagement »"</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"Autorise l\'application à utiliser les services d\'avant-plan avec le type « fileManagement »"</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"exécuter le service de premier plan avec le type « mediaProcessing »"</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"Autorise l\'application à utiliser les services de premier plan avec le type « mediaProcessing »"</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"exécuter le service d\'avant-plan avec le type « usage spécial »"</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Autoriser l\'application à utiliser les services d\'avant-plan avec le type « usage spécial »"</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"évaluer l\'espace de stockage de l\'application"</string> @@ -637,8 +635,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Utiliser le verrouillage de l\'écran"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Entrez votre verrouillage d\'écran pour continuer"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Appuyez fermement sur le capteur"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Empreinte digitale non reconnue. Réessayez."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Nettoyez le capteur d\'empreintes digitales et réessayez"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Nettoyez le capteur et réessayez"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Appuyez fermement sur le capteur"</string> @@ -702,8 +699,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"Visage non détecté. Tenez votre téléphone à hauteur des yeux."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Trop de mouvement. Tenez le téléphone immobile."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Veuillez inscrire votre visage à nouveau."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"Visage non reconnu. Réessayez."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Modifiez légèrement la position de votre tête"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Regardez droit dans le téléphone"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Regardez droit dans le téléphone"</string> diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml index f6e669c0ece4..8956904b7398 100644 --- a/core/res/res/values-fr/strings.xml +++ b/core/res/res/values-fr/strings.xml @@ -435,10 +435,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Autorise l\'appli à utiliser les services de premier plan avec le type \"systemExempted\""</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"exécuter un service de premier plan avec le type \"fileManagement\""</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"Autorise l\'appli à utiliser les services de premier plan avec le type \"fileManagement\""</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"exécuter un service de premier plan avec le type \"mediaProcessing\""</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"Autorise l\'appli à utiliser les services de premier plan avec le type \"mediaProcessing\""</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"exécuter un service de premier plan avec le type \"specialUse\""</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Autorise l\'appli à utiliser les services de premier plan avec le type \"specialUse\""</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"évaluer l\'espace de stockage de l\'application"</string> @@ -637,8 +635,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Utiliser verrouillage écran"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Utilisez le verrouillage de l\'écran pour continuer"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Appuyez fermement sur le lecteur"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Empreinte digitale non reconnue. Réessayez."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Nettoyez le lecteur d\'empreinte digitale et réessayez"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Nettoyez le lecteur et réessayez"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Appuyez fermement sur le lecteur"</string> @@ -702,8 +699,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"Visage non détecté. Tenez votre téléphone à hauteur des yeux."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Trop de mouvement. Ne bougez pas le téléphone."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Veuillez enregistrer à nouveau votre visage."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"Visage non reconnu. Réessayez."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Déplacez légèrement votre tête."</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Mettez-vous bien de face et regardez le téléphone"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Mettez-vous bien de face et regardez le téléphone"</string> diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml index 98560f3e880e..b1598b35ba2a 100644 --- a/core/res/res/values-gl/strings.xml +++ b/core/res/res/values-gl/strings.xml @@ -434,10 +434,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Permite que a aplicación faga uso de servizos en primeiro plano co tipo \"systemExempted\""</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"executar servizo en primeiro plano co tipo \"fileManagement\""</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"Permite que a aplicación faga uso de servizos en primeiro plano co tipo \"fileManagement\""</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"executar servizo en primeiro plano co tipo \"mediaProcessing\""</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"Permite que a aplicación faga uso de servizos en primeiro plano co tipo \"mediaProcessing\""</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"executar servizo en primeiro plano co tipo \"specialUse\""</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Permite que a aplicación faga uso de servizos en primeiro plano co tipo \"specialUse\""</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"medir o espazo de almacenamento da aplicación"</string> @@ -636,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Usar credencial do dispositivo"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Desbloquea a pantalla para continuar"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Preme o sensor con firmeza"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Non se recoñeceu a impresión dixital. Téntao de novo."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Limpa o sensor de impresión dixital e téntao de novo"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Limpa o sensor e téntao de novo"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Preme o sensor con firmeza"</string> @@ -701,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"Non se che ve a cara. Pon o teléfono diante dos ollos"</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Demasiado movemento. Non movas o teléfono."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Volve rexistrar a túa cara."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"Non se recoñeceu a cara. Téntao de novo."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Cambia lixeiramente a posición da cabeza"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Mira o teléfono de forma máis directa"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Mira o teléfono de forma máis directa"</string> diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml index 9d292017e833..023269f23dec 100644 --- a/core/res/res/values-gu/strings.xml +++ b/core/res/res/values-gu/strings.xml @@ -434,10 +434,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"ઍપને \"systemExempted\" પ્રકારની પરવાનગી વડે ફૉરગ્રાઉન્ડ સેવાઓનો ઉપયોગ કરવાની મંજૂરી આપે છે"</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"\"fileManagement\" પ્રકારની પરવાનગી વડે ફૉરગ્રાઉન્ડ સેવા ચલાવો"</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"ઍપને \"fileManagement\" પ્રકારની પરવાનગી વડે ફૉરગ્રાઉન્ડ સેવાઓનો ઉપયોગ કરવાની મંજૂરી આપે છે"</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"\"mediaProcessing\" પ્રકારની પરવાનગી વડે ફૉરગ્રાઉન્ડ સેવા ચલાવો"</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"ઍપને \"mediaProcessing\" પ્રકારની પરવાનગી વડે ફૉરગ્રાઉન્ડ સેવાઓનો ઉપયોગ કરવાની મંજૂરી આપે છે"</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"\"specialUse\" પ્રકારની પરવાનગી વડે ફૉરગ્રાઉન્ડ સેવા ચલાવો"</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"ઍપને \"specialUse\" પ્રકારની પરવાનગી વડે ફૉરગ્રાઉન્ડ સેવાઓનો ઉપયોગ કરવાની મંજૂરી આપે છે"</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"ઍપ્લિકેશન સંગ્રહ સ્થાન માપો"</string> @@ -636,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"સ્ક્રીન લૉકનો ઉપયોગ કરો"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"આગળ વધવા માટે તમારું સ્ક્રીન લૉક દાખલ કરો"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"સેન્સર પર જોરથી દબાવો"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"ફિંગરપ્રિન્ટ ઓળખી શકાઈ નથી. ફરી પ્રયાસ કરો."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"ફિંગરપ્રિન્ટ સેન્સર સાફ કરો અને ફરી પ્રયાસ કરો"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"સેન્સર સાફ કરો અને ફરી પ્રયાસ કરો"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"સેન્સર પર જોરથી દબાવો"</string> @@ -701,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"તમારો ચહેરો દેખાતો નથી. તમારા ફોનને આંખના લેવલ પર પકડી રાખો."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"ડિવાઇસ અસ્થિર છે. ફોનને સ્થિર રાખો."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"કૃપા કરીને તમારા ચહેરાની ફરી નોંધણી કરાવો."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"ચહેરો ઓળખાયો નથી. ફરી પ્રયાસ કરો."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"તમારા માથાની સ્થિતિ સહેજ બદલો"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"વધારે પ્રમાણમાં સીધું તમારા ફોન તરફ જુઓ"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"વધારે પ્રમાણમાં સીધું તમારા ફોન તરફ જુઓ"</string> diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml index 084b9568ea4a..a9221d8fdb08 100644 --- a/core/res/res/values-hi/strings.xml +++ b/core/res/res/values-hi/strings.xml @@ -434,10 +434,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"इससे ऐप्लिकेशन, \"systemExempted\" टाइप वाली फ़ोरग्राउंड सेवाओं का इस्तेमाल कर पाता है"</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"\"fileManagement\" टाइप वाली फ़ोरग्राउंड सेवा को चलाने की अनुमति दें"</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"इससे ऐप्लिकेशन को \"fileManagement\" टाइप वाली फ़ोरग्राउंड सेवाओं का इस्तेमाल करने की अनुमति मिलती है"</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"\"mediaProcessing\" टाइप वाली फ़ोरग्राउंड सेवा को चलाने की अनुमति दें"</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"इससे ऐप्लिकेशन, \"mediaProcessing\" टाइप वाली फ़ोरग्राउंड सेवाओं का इस्तेमाल कर पाता है"</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"\"specialUse\" टाइप वाली फ़ोरग्राउंड सेवा को चलाने की अनुमति दें"</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"इससे ऐप्लिकेशन, \"specialUse\" टाइप वाली फ़ोरग्राउंड सेवाओं का इस्तेमाल कर पाता है"</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"पता करें कि ऐप मेमोरी में कितनी जगह है"</string> @@ -636,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"स्क्रीन लॉक का क्रेडेंशियल इस्तेमाल करें"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"जारी रखने के लिए, अपने स्क्रीन लॉक की पुष्टि करें"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"सेंसर को उंगली से ज़ोर से दबाएं"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"फ़िंगरप्रिंट की पहचान नहीं हो पाई. फिर से कोशिश करें."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"फ़िंगरप्रिंट सेंसर को साफ़ करके फिर से कोशिश करें"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"फ़िंगरप्रिंट सेंसर को साफ़ करके फिर से कोशिश करें"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"सेंसर को उंगली से दबाकर रखें"</string> @@ -701,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"आपका चेहरा नहीं दिख रहा है. फ़ोन को अपनी आंखों की सीध में रखें."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"डिवाइस बहुत ज़्यादा हिल रहा है. फ़ोन को बिना हिलाएं पकड़ें."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"कृपया फिर से अपने चेहरे की पहचान कराएं."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"चेहरा नहीं पहचाना गया. फिर से कोशिश करें."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"अपने सिर की पोज़िशन को थोड़ा बदलें"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"अपने फ़ोन की तरफ़ बिलकुल सीधा देखें"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"अपने फ़ोन की तरफ़ बिलकुल सीधा देखें"</string> diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml index ca57b682f0f8..43433a3b6d23 100644 --- a/core/res/res/values-hr/strings.xml +++ b/core/res/res/values-hr/strings.xml @@ -435,10 +435,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Omogućuje aplikaciji da iskoristi usluge u prednjem planu s vrstom \"izuzeo sustav\""</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"pokreni uslugu u prednjem planu s vrstom fileManagement"</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"Aplikaciji omogućuje da iskoristi usluge u prednjem planu s vrstom fileManagement"</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"pokretanje usluge u prednjem planu s vrstom \"obrada medija\""</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"Omogućuje aplikaciji da iskoristi usluge u prednjem planu s vrstom \"obrada medija\""</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"pokretanje usluge u prednjem planu s vrstom \"posebna upotreba\""</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Omogućuje aplikaciji da iskoristi usluge u prednjem planu s vrstom \"posebna upotreba\""</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"mjerenje prostora za pohranu aplikacije"</string> @@ -637,8 +635,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Upotreba zaključavanja zaslona"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Upotrijebite zaključavanje zaslona da biste nastavili"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Čvrsto pritisnite senzor"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Otisak prsta nije prepoznat. Pokušajte ponovo."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Očistite senzor otiska prsta i pokušajte ponovno"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Očistite senzor i pokušajte ponovno"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Čvrsto pritisnite senzor"</string> @@ -702,8 +699,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"Vaše se lice ne vidi. Držite telefon u razini očiju."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Previše kretanja. Držite telefon mirno."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Ponovo registrirajte svoje lice."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"Lice nije prepoznato. Pokušajte ponovo."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Malo pomaknite glavu"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Gledajte ravno u telefon"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Gledajte ravno u telefon"</string> diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml index 2ccacffdaa14..64dee26f2d40 100644 --- a/core/res/res/values-hu/strings.xml +++ b/core/res/res/values-hu/strings.xml @@ -434,10 +434,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Engedélyezi az alkalmazásnak az előtérben lévő szolgáltatások használatát a következő típussal: „systemExempted”"</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"előtérben lévő szolgáltatás futtatása a következő típussal: „fileManagement\""</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"Lehetővé teszi az alkalmazásnak az előtérben futó szolgáltatások használatát a következő típussal: „fileManagement”"</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"előtérben lévő szolgáltatás futtatása a következő típussal: „mediaProcessing\""</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"Engedélyezi az alkalmazásnak az előtérben lévő szolgáltatások használatát a következő típussal: „mediaProcessing”"</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"előtérben lévő szolgáltatás futtatása a következő típussal: „specialUse\""</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Engedélyezi az alkalmazásnak az előtérben lévő szolgáltatások használatát a következő típussal: „specialUse”"</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"alkalmazás-tárhely felmérése"</string> @@ -636,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Képernyőzár használata"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"A folytatáshoz adja meg a képernyőzár hitelesítési adatait"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Nyomja meg határozottan az érzékelőt"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Ismeretlen ujjlenyomat. Próbálkozzon újra."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Tisztítsa meg az ujjlenyomat-érzékelőt, majd próbálja újra"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Tisztítsa meg az érzékelőt, majd próbálja újra"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Nyomja meg határozottan az érzékelőt"</string> @@ -701,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"Nem látszik az arca. Tartsa szemmagasságban a telefonját."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Túl sok a mozgás. Tartsa stabilan a telefont."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Rögzítsen újra képet az arcáról."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"Sikertelen arcfelismerés. Próbálkozzon újra."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Egy kicsit mozdítsa el a fejét"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Nézzen egyenesen a telefonjára"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Nézzen egyenesen a telefonjára"</string> diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml index 9480cc55222b..8a6d802c788f 100644 --- a/core/res/res/values-hy/strings.xml +++ b/core/res/res/values-hy/strings.xml @@ -434,10 +434,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Հավելվածին թույլ է տալիս օգտագործել systemExempted տեսակով ակտիվ ծառայությունները"</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"fileManagement տեսակով ակտիվ ծառայությունների գործարկում"</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"Թույլատրում է հավելվածին օգտագործել fileManagement տեսակով ակտիվ ծառայությունները"</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"mediaProcessing տեսակով ակտիվ ծառայությունների գործարկում"</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"Հավելվածին թույլ է տալիս օգտագործել mediaProcessing տեսակով ակտիվ ծառայությունները"</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"գործարկել specialUse տեսակով ակտիվ ծառայությունները"</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Հավելվածին թույլ է տալիս օգտագործել specialUse տեսակով ակտիվ ծառայությունները"</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"չափել հավելվածի պահոցի տարածքը"</string> @@ -636,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Էկրանի կողպում"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Շարունակելու համար ապակողպեք էկրանը"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Մատը ուժեղ սեղմեք սկաների վրա"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Մատնահետքը չի ճանաչվել։ Նորից փորձեք։"</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Մաքրեք մատնահետքերի սկաները և նորից փորձեք"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Մաքրեք սկաները և նորից փորձեք"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Մատը ուժեղ սեղմեք սկաների վրա"</string> @@ -701,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"Դեմքը չի երևում։ Հեռախոսը պահեք աչքերի մակարդակում։"</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Շատ եք շարժում։ Հեռախոսն անշարժ պահեք։"</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Նորից փորձեք։"</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"Դեմքը չի ճանաչվել։ Նորից փորձեք։"</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Թեթևակի փոխեք գլխի դիրքը"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Նայեք ուղիղ էկրանին"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Նայեք ուղիղ էկրանին"</string> diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml index 50ef6a0659c2..991d69fb1d83 100644 --- a/core/res/res/values-in/strings.xml +++ b/core/res/res/values-in/strings.xml @@ -434,10 +434,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Mengizinkan aplikasi menggunakan layanan latar depan dengan jenis \"systemExempted\""</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"menjalankan layanan latar depan dengan jenis \"fileManagement\""</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"Mengizinkan aplikasi menggunakan layanan latar depan dengan jenis \"fileManagement\""</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"menjalankan layanan latar depan dengan jenis \"mediaProcessing\""</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"Mengizinkan aplikasi menggunakan layanan latar depan dengan jenis \"mediaProcessing\""</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"menjalankan layanan latar depan dengan jenis \"specialUse\""</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Mengizinkan aplikasi menggunakan layanan latar depan dengan jenis \"specialUse\""</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"mengukur ruang penyimpanan aplikasi"</string> @@ -636,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Gunakan kunci layar"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Masukkan kunci layar untuk melanjutkan"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Tekan sensor dengan kuat"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Sidik jari tidak dikenali. Coba lagi."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Bersihkan sensor sidik jari lalu coba lagi"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Bersihkan sensor lalu coba lagi"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Tekan sensor dengan kuat"</string> @@ -701,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"Wajah tidak terlihat. Pegang ponsel sejajar mata."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Terlalu banyak gerakan. Stabilkan ponsel."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Daftarkan ulang wajah Anda."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"Wajah tidak dikenali. Coba lagi."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Ubah sedikit posisi kepala"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Lihat lebih lurus ke arah ponsel"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Lihat lebih lurus ke arah ponsel"</string> diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml index 804f1319e6c0..8bab2d721f77 100644 --- a/core/res/res/values-is/strings.xml +++ b/core/res/res/values-is/strings.xml @@ -434,10 +434,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Leyfir forritinu að nota forgrunnsþjónustu af gerðinni „systemExempted“"</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"keyra forgrunnsþjónustu af gerðinni „fileManagement“"</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"Leyfir forritinu að nota forgrunnsþjónustur af gerðinni „fileManagement“"</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"Keyra forgrunnsþjónustu af gerðinni „mediaProcessing“"</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"Leyfir forritinu að nota forgrunnsþjónustu af gerðinni „mediaProcessing“"</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"keyra forgrunnsþjónustu af gerðinni „specialUse“"</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Leyfir forritinu að nota forgrunnsþjónustu af gerðinni „specialUse“"</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"mæla geymslurými forrits"</string> @@ -636,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Nota skjálás"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Sláðu inn skjálásinn þinn til að halda áfram"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Ýttu ákveðið á lesarann"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Ekki tókst að bera kennsl á fingrafar. Reyndu aftur."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Hreinsaðu fingrafaralesarann og reyndu aftur"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Hreinsaðu lesarann og reyndu aftur"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Ýttu ákveðið á lesarann"</string> @@ -701,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"Sé ekki andlitið á þér. Haltu símanum í augnhæð."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Of mikil hreyfing. Haltu símanum stöðugum."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Skráðu nafnið þitt aftur."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"Ekki tókst að bera kennsl á andlit. Reyndu aftur."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Færðu höfuðið aðeins til"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Horfðu beint á símann"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Horfðu beint á símann"</string> diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml index c1ef0ea2fdbd..b2180ab3f319 100644 --- a/core/res/res/values-it/strings.xml +++ b/core/res/res/values-it/strings.xml @@ -435,10 +435,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Consente all\'app di usare i servizi in primo piano con il tipo \"systemExempted\""</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"Eseguire servizi in primo piano con il tipo \"fileManagement\""</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"Consente all\'app di usare i servizi in primo piano con il tipo \"fileManagement\""</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"Eseguire servizi in primo piano con il tipo \"mediaProcessing\""</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"Consente all\'app di usare i servizi in primo piano con il tipo \"mediaProcessing\""</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"Esecuzione di servizi in primo piano con il tipo \"specialUse\""</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Consente all\'app di usare i servizi in primo piano con il tipo \"specialUse\""</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"calcolo spazio di archiviazione applicazioni"</string> @@ -637,8 +635,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Usa il blocco schermo"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Inserisci il blocco schermo per continuare"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Premi con decisione sul sensore"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Impronta non riconosciuta. Riprova."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Pulisci il sensore di impronte digitali e riprova"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Pulisci il sensore e riprova"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Premi con decisione sul sensore"</string> @@ -702,8 +699,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"Volto non visibile. Tieni lo smartphone all\'altezza degli occhi."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Troppo movimento. Tieni fermo il telefono."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Ripeti l\'acquisizione del volto."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"Volto non riconosciuto. Riprova."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Cambia leggermente la posizione della testa"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Guarda dritto nello smartphone"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Guarda dritto nello smartphone"</string> diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml index c1892186c9c0..593668a87e65 100644 --- a/core/res/res/values-iw/strings.xml +++ b/core/res/res/values-iw/strings.xml @@ -435,10 +435,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"ההרשאה הזו מאפשרת לאפליקציה להשתמש בשירותים שפועלים בחזית מסוג \"systemExempted\""</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"הפעלת שירות שפועל בחזית מסוג \"fileManagement\""</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"ההרשאה הזו מאפשרת לאפליקציה להתבסס על שירותים שפועלים בחזית מסוג \"fileManagement\""</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"הפעלת שירות שפועל בחזית מסוג \"mediaProcessing\""</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"ההרשאה הזו מאפשרת לאפליקציה להשתמש בשירותים שפועלים בחזית מסוג \"mediaProcessing\""</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"הפעלת שירות שפועל בחזית מסוג \"specialUse\""</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"ההרשאה הזו מאפשרת לאפליקציה להשתמש בשירותים שפועלים בחזית מסוג \"specialUse\""</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"מדידת נפח האחסון של אפליקציות"</string> @@ -637,8 +635,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"שימוש בנעילת מסך"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"יש לבטל את נעילת המסך כדי להמשיך"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"צריך ללחוץ לחיצה חזקה על החיישן"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"טביעת האצבע לא זוהתה. אפשר לנסות שוב."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"עליך לנקות את חיישן טביעות האצבע ולנסות שוב"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"עליך לנקות את החיישן ולנסות שוב"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"צריך ללחוץ חזק על החיישן"</string> @@ -702,8 +699,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"לא רואים את הפנים שלך. יש להחזיק את הטלפון בגובה העיניים."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"יותר מדי תנועה. יש להחזיק את הטלפון בצורה יציבה."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"יש לסרוק שוב את הפנים."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"הפנים לא זוהו. אפשר לנסות שוב."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"צריך לשנות מעט את תנוחת הראש"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"צריך להביט ישירות בטלפון"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"צריך להביט ישירות בטלפון"</string> diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml index 7bb322cc6c37..3a904b6467bc 100644 --- a/core/res/res/values-ja/strings.xml +++ b/core/res/res/values-ja/strings.xml @@ -434,10 +434,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"タイプが「systemExempted」のフォアグラウンド サービスの使用をアプリに許可します"</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"タイプが「fileManagement」のフォアグラウンド サービスの実行"</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"タイプが「fileManagement」のフォアグラウンド サービスの使用をアプリに許可します"</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"タイプが「mediaProcessing」のフォアグラウンド サービスの実行"</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"タイプが「mediaProcessing」のフォアグラウンド サービスの使用をアプリに許可します"</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"タイプが「specialUse」のフォアグラウンド サービスの実行"</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"タイプが「specialUse」のフォアグラウンド サービスの使用をアプリに許可します"</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"アプリのストレージ容量の計測"</string> @@ -636,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"画面ロックの使用"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"続行するには画面ロックを入力してください"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"センサーにしっかりと押し当ててください"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"指紋を認識できません。もう一度お試しください。"</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"指紋認証センサーの汚れを取り除いて、もう一度お試しください"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"センサーの汚れを取り除いて、もう一度お試しください"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"センサーにしっかりと押し当ててください"</string> @@ -701,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"顔を確認できません。スマートフォンを目の高さに合わせます。"</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"あまり動かさないでください。安定させてください。"</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"顔を登録し直してください。"</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"顔を認識できません。もう一度お試しください。"</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"顔の位置を少し変えてください"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"もっとまっすぐスマートフォンに顔を向けてください"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"もっとまっすぐスマートフォンに顔を向けてください"</string> diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml index 7b7f267c6898..e77068d8f0d5 100644 --- a/core/res/res/values-ka/strings.xml +++ b/core/res/res/values-ka/strings.xml @@ -434,10 +434,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"ნებას რთავს აპს, გამოიყენოს პრიორიტეტული სერვისები ტიპის „გათავისუფლებულისისტემა“ შემთხვევაში"</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"პრიორიტეტული სერვისის გაშვება ტიპის „ფაილებისმართვა“ შემთხვევაში"</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"საშუალებას აძლევს აპს, გამოიყენოს პრიორიტეტული სერვისები ტიპის „ფაილისმართვა“ შემთხვევაში"</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"პრიორიტეტული სერვისის გაშვება „mediaProcessing“ ტიპის შემთხვევაში"</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"აპს რთავს ნებას, გამოიყენოს პრიორიტეტული სერვისები „mediaProcessing\" ტიპის შემთხვევაში"</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"პრიორიტეტული სერვისის გაშვება ტიპის „სპეციალურიგამოყენება“ შემთხვევაში"</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"ნებას რთავს აპს, გამოიყენოს პრიორიტეტული სერვისები ტიპის „სპეციალურიგამოყენება“ შემთხვევაში"</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"აპის მეხსიერების სივრცის გაზომვა"</string> @@ -636,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"გამოიყენეთ ეკრანის დაბლოკვა"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"გასაგრძელებლად შედით ეკრანის დაბლოკვაში"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"მაგრად დააჭირეთ სენსორს"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"თითის ანაბეჭდის ამოცნობა ვერ მოხერხდა. ცადეთ ხელახლა."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"გაწმინდეთ თითის ანაბეჭდის სენსორი და ხელახლა ცადეთ"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"გაწმინდეთ სენსორი და ხელახლა ცადეთ"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"მაგრად დააჭირეთ სენსორს"</string> @@ -701,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"სახე არ ჩანს. დაიჭირეთ ტელ. თვალის დონეზე."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"მეტისმეტად მოძრაობთ. მყარად დაიჭირეთ ტელეფონი."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"გთხოვთ, ხელახლა დაარეგისტრიროთ თქვენი სახე."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"სახის ამოცნობა ვერ მოხერხდა. ცადეთ ხელახლა."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"ოდნავ შეცვალეთ თავის პოზიცია"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"პირდაპირ უყურეთ ტელეფონს"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"პირდაპირ უყურეთ ტელეფონს"</string> diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml index fa2a798b5663..e6af91206c67 100644 --- a/core/res/res/values-kk/strings.xml +++ b/core/res/res/values-kk/strings.xml @@ -434,10 +434,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Қолданбаға \"systemExempted\" түріне жататын экрандық режимдегі қызметтерді пайдалануға рұқсат беріледі."</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"\"fileManagement\" түрі бар экрандық режимдегі қызметті іске қосу"</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"Қолданбаға \"fileManagement\" түріне жататын экрандық режимдегі қызметтерді пайдалануға рұқсат беріледі."</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"\"mediaProcessing\" түріне жататын экрандық режимдегі қызметті іске қосу"</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"Қолданбаға \"mediaProcessing\" түріне жататын экрандық режимдегі қызметтерді пайдалануға рұқсат беріледі."</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"\"specialUse\" түріне жататын экрандық режимдегі қызметті іске қосу"</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Қолданбаға \"specialUse\" түріне жататын экрандық режимдегі қызметтерді пайдалануға рұқсат беріледі."</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"қолданба жадындағы бос орынды өлшеу"</string> @@ -636,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Экран құлпын пайдалану"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Жалғастыру үшін экран құлпын енгізіңіз."</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Сканерді қатты басыңыз"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Саусақ ізі танылмады. Қайталап көріңіз."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Саусақ ізін оқу сканерін тазалап, әрекетті қайталаңыз."</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Сканерді тазалап, әрекетті қайталаңыз."</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Сканерді қатты басыңыз"</string> @@ -701,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"Бетіңіз көрінбей тұр. Телефонды көз деңгейінде ұстаңыз."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Қозғалыс тым көп. Телефонды қозғалтпаңыз."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Қайта тіркеліңіз."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"Бет танылмады. Қайталап көріңіз."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Басыңыздың қалпын сәл өзгертіңіз."</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Телефонға тура қараңыз"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Телефонға тура қараңыз"</string> diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml index ab51e6efe9cf..713352725fde 100644 --- a/core/res/res/values-km/strings.xml +++ b/core/res/res/values-km/strings.xml @@ -434,10 +434,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"អនុញ្ញាតឱ្យកម្មវិធីប្រើប្រាស់សេវាកម្មផ្ទៃខាងមុខជាមួយនឹងប្រភេទ \"systemExempted\""</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"ដំណើរការសេវាកម្មផ្ទៃខាងមុខជាមួយនឹងប្រភេទ \"fileManagement\""</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"អនុញ្ញាតឱ្យកម្មវិធីប្រើប្រាស់សេវាកម្មផ្ទៃខាងមុខជាមួយនឹងប្រភេទ \"fileManagement\""</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"ដំណើរការសេវាកម្មផ្ទៃខាងមុខជាមួយនឹងប្រភេទ \"mediaProcessing\""</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"អនុញ្ញាតឱ្យកម្មវិធីប្រើប្រាស់សេវាកម្មផ្ទៃខាងមុខជាមួយនឹងប្រភេទ \"mediaProcessing\""</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"ដំណើរការសេវាកម្មផ្ទៃខាងមុខជាមួយនឹងប្រភេទ \"specialUse\""</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"អនុញ្ញាតឱ្យកម្មវិធីប្រើប្រាស់សេវាកម្មផ្ទៃខាងមុខជាមួយនឹងប្រភេទ \"specialUse\""</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"វាស់ទំហំការផ្ទុកកម្មវិធី"</string> @@ -636,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"ប្រើការចាក់សោអេក្រង់"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"បញ្ចូលការចាក់សោអេក្រង់របស់អ្នក ដើម្បីបន្ត"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"សង្កត់លើសេនស័រឱ្យណែន"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"មិនស្គាល់ស្នាមម្រាមដៃទេ។ សូមព្យាយាមម្ដងទៀត។"</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"សម្អាតឧបករណ៍ចាប់ស្នាមម្រាមដៃ រួចព្យាយាមម្ដងទៀត"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"សម្អាតឧបករណ៍ចាប់សញ្ញា រួចព្យាយាមម្ដងទៀត"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"សង្កត់លើសេនស័រឱ្យណែន"</string> @@ -701,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"មើលមិនឃើញមុខរបស់អ្នកទេ។ កាន់ទូរសព្ទរបស់អ្នកដាក់ត្រឹមភ្នែក។"</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"មានចលនាខ្លាំងពេក។ សូមកាន់ទូរសព្ទឱ្យនឹង។"</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"សូមស្កេនបញ្ចូលមុខរបស់អ្នកម្ដងទៀត។"</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"មិនស្គាល់មុខទេ។ សូមព្យាយាមម្ដងទៀត។"</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"ប្ដូរទីតាំងក្បាលរបស់អ្នកតិចៗ"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"មើលទូរសព្ទរបស់អ្នកឱ្យចំជាងនេះ"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"មើលទូរសព្ទរបស់អ្នកឱ្យចំជាងនេះ"</string> diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml index 625ade1ca12d..1e9414acb8b1 100644 --- a/core/res/res/values-kn/strings.xml +++ b/core/res/res/values-kn/strings.xml @@ -434,10 +434,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"\"systemExempted\" ಪ್ರಕಾರದೊಂದಿಗೆ ಮುನ್ನೆಲೆ ಸೇವೆಗಳನ್ನು ಬಳಸಲು ಆ್ಯಪ್ಗೆ ಅನುಮತಿಸುತ್ತದೆ"</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"\"fileManagement\" ಪ್ರಕಾರದೊಂದಿಗೆ ಮುನ್ನೆಲೆ ಸೇವೆಯನ್ನು ರನ್ ಮಾಡಿ"</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"\"fileManagement\" ಪ್ರಕಾರದೊಂದಿಗೆ ಮುನ್ನೆಲೆ ಸೇವೆಗಳನ್ನು ಬಳಸಲು ಆ್ಯಪ್ಗೆ ಅನುಮತಿಸುತ್ತದೆ"</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"\"mediaProcessing\" ಪ್ರಕಾರದೊಂದಿಗೆ ಮುನ್ನೆಲೆ ಸೇವೆಯನ್ನು ರನ್ ಮಾಡಿ"</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"\"mediaProcessing\" ಪ್ರಕಾರದೊಂದಿಗೆ ಮುನ್ನೆಲೆ ಸೇವೆಗಳನ್ನು ಬಳಸಲು ಆ್ಯಪ್ಗೆ ಅನುಮತಿಸುತ್ತದೆ"</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"\"specialUse\" ಪ್ರಕಾರದೊಂದಿಗೆ ಮುನ್ನೆಲೆ ಸೇವೆಯನ್ನು ರನ್ ಮಾಡಿ"</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"\"specialUse\" ಪ್ರಕಾರದೊಂದಿಗೆ ಮುನ್ನೆಲೆ ಸೇವೆಗಳನ್ನು ಬಳಸಲು ಆ್ಯಪ್ಗೆ ಅನುಮತಿಸುತ್ತದೆ"</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"ಅಪ್ಲಿಕೇಶನ್ ಸಂಗ್ರಹ ಸ್ಥಳವನ್ನು ಅಳೆಯಿರಿ"</string> @@ -636,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"ಸ್ಕ್ರೀನ್ ಲಾಕ್ ಬಳಸಿ"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"ಮುಂದುವರಿಯಲು ನಿಮ್ಮ ಸ್ಕ್ರೀನ್ ಲಾಕ್ ಅನ್ನು ನಮೂದಿಸಿ"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"ಸೆನ್ಸರ್ ಮೇಲೆ ಗಟ್ಟಿಯಾಗಿ ಒತ್ತಿರಿ"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"ಫಿಂಗರ್ ಪ್ರಿಂಟ್ ಅನ್ನು ಗುರುತಿಸಲಾಗಿಲ್ಲ. ಪುನಃ ಪ್ರಯತ್ನಿಸಿ."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"ಫಿಂಗರ್ ಪ್ರಿಂಟ್ ಸೆನ್ಸರ್ ಸ್ವಚ್ಛಗೊಳಿಸಿ ಹಾಗೂ ಪುನಃ ಪ್ರಯತ್ನಿಸಿ"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"ಸೆನ್ಸರ್ ಸ್ವಚ್ಛಗೊಳಿಸಿ ಹಾಗೂ ಪುನಃ ಪ್ರಯತ್ನಿಸಿ"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"ಸೆನ್ಸರ್ ಮೇಲೆ ಗಟ್ಟಿಯಾಗಿ ಒತ್ತಿರಿ"</string> @@ -701,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"ನಿಮ್ಮ ಮುಖ ಕಾಣಿಸುತ್ತಿಲ್ಲ. ನಿಮ್ಮ ಫೋನ್ ಅನ್ನು ಕಣ್ಣಿನ ನೇರಕ್ಕೆ ಹಿಡಿದುಕೊಳ್ಳಿ."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"ತುಂಬಾ ಅಲುಗಾಡುತ್ತಿದೆ ಫೋನ್ ಅನ್ನು ಸ್ಥಿರವಾಗಿ ಹಿಡಿಯಿರಿ."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"ನಿಮ್ಮ ಮುಖವನ್ನು ಮರುನೋಂದಣಿ ಮಾಡಿ."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"ಮುಖ ಗುರುತಿಸಲಾಗಿಲ್ಲ. ಪುನಃ ಪ್ರಯತ್ನಿಸಿ."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"ನಿಮ್ಮ ತಲೆಯ ಸ್ಥಾನವನ್ನು ಸ್ವಲ್ಪ ಬದಲಾಯಿಸಿ"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"ನಿಮ್ಮ ಫೋನ್ ಅನ್ನು ನೇರವಾಗಿ ನೋಡಿ"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"ನಿಮ್ಮ ಫೋನ್ ಅನ್ನು ನೇರವಾಗಿ ನೋಡಿ"</string> diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml index a40a7f4d8562..f78d0af821ce 100644 --- a/core/res/res/values-ko/strings.xml +++ b/core/res/res/values-ko/strings.xml @@ -434,10 +434,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"앱에서 \'systemExempted\' 유형의 포그라운드 서비스를 사용하도록 허용합니다."</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"\'fileManagement\' 유형의 포그라운드 서비스 실행"</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"앱에서 \'fileManagement\' 유형의 포그라운드 서비스를 사용하도록 허용합니다."</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"\'mediaProcessing\' 유형의 포그라운드 서비스 실행"</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"앱에서 \'mediaProcessing\' 유형의 포그라운드 서비스를 사용하도록 허용합니다."</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"\'specialUse\' 유형의 포그라운드 서비스 실행"</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"앱에서 \'specialUse\' 유형의 포그라운드 서비스를 사용하도록 허용합니다."</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"앱 저장공간 계산"</string> @@ -636,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"화면 잠금 사용"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"계속하려면 화면 잠금용 사용자 인증 정보를 입력하세요"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"센서를 세게 누르세요"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"지문을 인식할 수 없습니다. 다시 시도해 주세요."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"지문 센서를 닦은 후 다시 시도해 보세요."</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"센서를 닦은 후 다시 시도해 보세요."</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"센서를 세게 누르세요"</string> @@ -701,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"얼굴이 보이지 않습니다. 눈높이에 맞춰 휴대전화를 들어 주세요"</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"너무 많이 움직였습니다. 휴대전화를 흔들리지 않게 잡으세요."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"얼굴을 다시 등록해 주세요."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"얼굴을 인식할 수 없습니다. 다시 시도해 주세요."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"얼굴의 위치를 조금 변경해 주세요."</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"휴대전화를 좀 더 정면에서 바라보세요."</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"휴대전화를 좀 더 정면에서 바라보세요."</string> diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml index cfa0983e0e14..e7ee2e8fc226 100644 --- a/core/res/res/values-ky/strings.xml +++ b/core/res/res/values-ky/strings.xml @@ -434,10 +434,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Колдонмолорго алдынкы пландагы \"systemExempted\" түрүндөгү кызматтарды колдонууга уруксат берет"</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"алдынкы пландагы \"fileManagement\" түрүндөгү кызматты аткаруу"</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"Колдонмолорго алдынкы пландагы \"fileManagement\" түрүндөгү кызматтарды колдонууга уруксат берет"</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"алдыңкы пландагы \"mediaProcessing\" түрүндөгү кызматты иштетүү"</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"Колдонмолорго алдыңкы пландагы \"mediaProcessing\" түрүндөгү кызматтарды колдонууга уруксат берет"</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"алдынкы пландагы \"specialUse\" түрүндөгү кызматты аткаруу"</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Колдонмолорго алдынкы пландагы \"specialUse\" түрүндөгү кызматтарды колдонууга уруксат берет"</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"колдонмо сактагычынын мейкиндигин өлчөө"</string> @@ -636,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Экран кулпусун колдонуу"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Улантуу үчүн экрандын кулпусун киргизиңиз"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Сенсорду катуу басыңыз"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Манжа изи таанылган жок. Кайра аракет кылыңыз."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Манжа изинин сенсорун тазалап, кайра аракет кылыңыз"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Сенсорду тазалап, кайра аракет кылыңыз"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Сенсорду катуу басыңыз"</string> @@ -701,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"Жүзүңүз көрүнбөй жатат. Телефонду маңдайыңызга кармаңыз."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Кыймылдап жибердиңиз. Телефонду түз кармаңыз."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Жүзүңүздү кайра таанытыңыз."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"Жүз таанылган жок. Кайра аракет кылыңыз."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Башыңызды бир аз буруңуз"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Телефонуңузду караңыз"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Телефонуңузду караңыз"</string> diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml index 653de36aca6d..84fea7383ab5 100644 --- a/core/res/res/values-lo/strings.xml +++ b/core/res/res/values-lo/strings.xml @@ -434,10 +434,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"ອະນຸຍາດໃຫ້ແອັບໃຊ້ປະໂຫຍດຈາກບໍລິການທີ່ເຮັດວຽກຢູ່ເບື້ອງໜ້າໂດຍມີປະເພດເປັນ \"ໄດ້ຮັບການຍົກເວັ້ນຈາກລະບົບ\""</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"ເອີ້ນໃຊ້ບໍລິການທີ່ເຮັດວຽກຢູ່ເບື້ອງໜ້າໂດຍມີປະເພດເປັນ \"ການຈັດການໄຟລ໌\""</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"ອະນຸຍາດໃຫ້ແອັບໃຊ້ປະໂຫຍດຈາກບໍລິການທີ່ເຮັດວຽກຢູ່ເບື້ອງໜ້າໂດຍມີປະເພດເປັນ \"ການຈັດການໄຟລ໌\""</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"ເອີ້ນໃຊ້ບໍລິການທີ່ເຮັດວຽກຢູ່ເບື້ອງໜ້າໂດຍມີປະເພດເປັນ \"mediaProcessing\""</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"ອະນຸຍາດໃຫ້ແອັບໃຊ້ປະໂຫຍດຈາກບໍລິການທີ່ເຮັດວຽກຢູ່ເບື້ອງໜ້າໂດຍມີປະເພດເປັນ \"mediaProcessing\""</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"ເອີ້ນໃຊ້ບໍລິການທີ່ເຮັດວຽກຢູ່ເບື້ອງໜ້າໂດຍມີປະເພດເປັນ \"ການນຳໃຊ້ພິເສດ\""</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"ອະນຸຍາດໃຫ້ແອັບໃຊ້ປະໂຫຍດຈາກບໍລິການທີ່ເຮັດວຽກຢູ່ເບື້ອງໜ້າໂດຍມີປະເພດເປັນ \"ການນຳໃຊ້ພິເສດ\""</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"ກວດສອບພື້ນທີ່ຈັດເກັບຂໍ້ມູນແອັບຯ"</string> @@ -636,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"ໃຊ້ການລັອກໜ້າຈໍ"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"ໃສ່ການລັອກໜ້າຈໍຂອງທ່ານເພື່ອສືບຕໍ່"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"ກົດຢູ່ເຊັນເຊີໃຫ້ແໜ້ນ"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"ບໍ່ສາມາດຈຳແນກລາຍນິ້ວມືໄດ້. ລອງໃໝ່."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"ໃຫ້ອະນາໄມເຊັນເຊີລາຍນິ້ວມືແລ້ວລອງໃໝ່"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"ໃຫ້ອະນາໄມເຊັນເຊີແລ້ວລອງໃໝ່"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"ກົດຢູ່ເຊັນເຊີໃຫ້ແໜ້ນ"</string> @@ -701,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"ບໍ່ເຫັນໃບໜ້າຂອງທ່ານ. ຖືໂທລະສັບຂອງທ່ານໄວ້ໃນລະດັບສາຍຕາ."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"ເຄື່ອນໄຫວຫຼາຍເກີນໄປ. ກະລຸນາຖືໂທລະສັບໄວ້ຊື່ໆ."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"ກະລຸນາລົງທະບຽນອຸປະກອນຂອງທ່ານອີກເທື່ອໜຶ່ງ."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"ບໍ່ສາມາດຈຳແນກໜ້າໄດ້. ລອງໃໝ່."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"ປ່ຽນຕຳແໜ່ງຂອງຫົວທ່ານເລັກນ້ອຍ"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"ເບິ່ງຊື່ໆໄປຫາໂທລະສັບຂອງທ່ານໃຫ້ຫຼາຍຂຶ້ນ"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"ເບິ່ງຊື່ໆໄປຫາໂທລະສັບຂອງທ່ານໃຫ້ຫຼາຍຂຶ້ນ"</string> diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml index 4733552be636..0991daa44e00 100644 --- a/core/res/res/values-lt/strings.xml +++ b/core/res/res/values-lt/strings.xml @@ -436,10 +436,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Programai leidžiama naudoti priekinio plano paslaugas, kurių tipas „systemExempted“"</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"Priekinio plano paslaugos, kurios tipas „fileManagement“, vykdymas"</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"Leidžiama programai naudoti priekinio plano paslaugas, kurių tipas „fileManagement“"</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"vykdyti priekinio plano paslaugą, kurios tipas „mediaProcessing“"</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"Programai leidžiama naudoti priekinio plano paslaugas, kurių tipas „mediaProcessing“"</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"paleisti priekinio plano paslaugą, kurios tipas „specialUse“"</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Programai leidžiama naudoti priekinio plano paslaugas, kurių tipas „specialUse“"</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"matuoti programos atmintinės vietą"</string> @@ -638,8 +636,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Naudoti ekrano užraktą"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Jei norite tęsti, įveskite ekrano užraktą"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Stipriai paspauskite jutiklį"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Piršto atspaudas neatpažintas. Bandykite dar kartą."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Nuvalykite kontrolinio kodo jutiklį ir bandykite dar kartą"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Nuvalykite jutiklį ir bandykite dar kartą"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Tvirtai paspauskite jutiklį"</string> @@ -703,8 +700,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"Nepavyko pamatyti jūsų veido. Laikykite telefoną akių lygyje."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Įrenginys per daug judinamas. Nejudink. telefono."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Užregistruokite veidą iš naujo."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"Veidas neatpažintas. Bandykite dar kartą."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Kaskart šiek tiek pakeiskite galvos poziciją"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Žiūrėkite tiesiai į telefoną"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Žiūrėkite tiesiai į telefoną"</string> diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml index 0f4e3f9bfddb..68f496a9ad44 100644 --- a/core/res/res/values-lv/strings.xml +++ b/core/res/res/values-lv/strings.xml @@ -435,10 +435,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Ļauj lietotnei izmantot šāda veida priekšplāna pakalpojumus: systemExempted"</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"izpildīt šāda veida priekšplāna pakalpojumu: fileManagement"</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"Ļauj lietotnei izmantot šāda veida priekšplāna pakalpojumus: fileManagement"</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"izpildīt šāda veida priekšplāna pakalpojumu: mediaProcessing"</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"Ļauj lietotnei izmantot šāda veida priekšplāna pakalpojumus: mediaProcessing"</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"izpildīt šāda veida priekšplāna pakalpojumu: specialUse"</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Ļauj lietotnei izmantot šāda veida priekšplāna pakalpojumus: specialUse"</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"noteikt vietas apjomu lietotnes atmiņā"</string> @@ -637,8 +635,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Ekrāna bloķēšanas metodes izmantošana"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Lai turpinātu, ievadiet ekrāna bloķēšanas informāciju"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Stingri spiediet pirkstu pie sensora"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Pirksta nospiedums netika atpazīts. Mēģiniet vēlreiz."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Notīriet pirkstu nospiedumu sensoru un mēģiniet vēlreiz"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Notīriet sensoru un mēģiniet vēlreiz"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Stingri spiediet pirkstu pie sensora"</string> @@ -702,8 +699,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"Seja nav redzama. Turiet tālruni acu līmenī."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Pārāk daudz kustību. Nekustīgi turiet tālruni."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Lūdzu, atkārtoti reģistrējiet savu seju."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"Seja netika atpazīta. Mēģiniet vēlreiz."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Nedaudz mainiet galvas pozīciju."</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Skatieties tieši uz tālruni"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Skatieties tieši uz tālruni"</string> diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml index fd8daacb1498..8828ab466e14 100644 --- a/core/res/res/values-mk/strings.xml +++ b/core/res/res/values-mk/strings.xml @@ -434,10 +434,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Дозволува апликацијата да ги користи во преден план услугите со типот „systemExempted“"</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"Извршување услуга во преден план со типот „fileManagement“"</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"Дозволува апликацијата да ги користи услугите во преден план со типот „fileManagement“"</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"извршување услуга во преден план со типот „mediaProcessing“"</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"Дозволува апликацијата да ги користи услугите во преден план со типот „mediaProcessing“"</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"да извршува во преден план услуга со типот „specialUse“"</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Дозволува апликацијата да ги користи во преден план услугите со типот „specialUse“"</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"измери простор за складирање на апликацијата"</string> @@ -636,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Користи заклучување екран"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Внесете го заклучувањето на екранот за да продолжите"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Цврсто притиснете на сензорот"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Отпечатокот не е препознаен. Обидете се повторно."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Исчистете го сензорот за отпечатоци и обидете се повторно"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Исчистете го сензорот и обидете се повторно"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Цврсто притиснете на сензорот"</string> @@ -701,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"Не се гледа ликот. Држете го телефонот во висина на очите."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Премногу движење. Држете го телефонот стабилно."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Повторно регистрирајте го лицето."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"Ликот не е препознаен. Обидете се повторно."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Малку сменете ја положбата на главата"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Гледајте подиректно во телефонот"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Гледајте подиректно во телефонот"</string> diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml index a001de325e31..cb0cb33073b5 100644 --- a/core/res/res/values-ml/strings.xml +++ b/core/res/res/values-ml/strings.xml @@ -634,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"സ്ക്രീൻ ലോക്ക് ഉപയോഗിക്കുക"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"തുടരാൻ നിങ്ങളുടെ സ്ക്രീൻ ലോക്ക് നൽകുക"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"സെൻസറിൽ നന്നായി അമർത്തുക"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"ഫിംഗർപ്രിന്റ് തിരിച്ചറിഞ്ഞിട്ടില്ല. വീണ്ടും ശ്രമിക്കൂ."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"ഫിംഗർപ്രിന്റ് സെൻസർ വൃത്തിയാക്കിയ ശേഷം വീണ്ടും ശ്രമിക്കുക"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"സെൻസർ വൃത്തിയാക്കിയ ശേഷം വീണ്ടും ശ്രമിക്കുക"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"സെൻസറിൽ നന്നായി അമർത്തുക"</string> @@ -699,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"മുഖം കാണുന്നില്ല. ഫോൺ കണ്ണിന് നേരെ പിടിക്കുക."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"വളരെയധികം ചലനം. ഫോൺ അനക്കാതെ നേരെ പിടിക്കുക."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"നിങ്ങളുടെ മുഖം വീണ്ടും എൻറോൾ ചെയ്യുക."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"മുഖം തിരിച്ചറിഞ്ഞിട്ടില്ല. വീണ്ടും ശ്രമിക്കൂ."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"നിങ്ങളുടെ തലയുടെ സ്ഥാനം ചെറുതായി മാറ്റുക"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"കൂടുതൽ കൃത്യമായി ഫോണിന് നേരെ നോക്കുക"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"കൂടുതൽ കൃത്യമായി ഫോണിന് നേരെ നോക്കുക"</string> diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml index 16b5766e190f..9bff0da52df1 100644 --- a/core/res/res/values-mn/strings.xml +++ b/core/res/res/values-mn/strings.xml @@ -434,10 +434,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Аппад \"systemExempted\" төрөлтэй нүүрэн талын үйлчилгээнүүдийг ашиглахыг зөвшөөрнө"</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"\"FileManagement\" төрөлтэй нүүрэн талын үйлчилгээг ажиллуулах"</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"Аппад \"fileManagement\" төрөлтэй нүүрэн талын үйлчилгээнүүдийг ашиглахыг зөвшөөрнө"</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"\"mediaProcessing\" төрөлтэй нүүрэн талын үйлчилгээг ажиллуулах"</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"Аппад \"mediaProcessing\" төрөлтэй нүүрэн талын үйлчилгээнүүдийг ашиглахыг зөвшөөрнө"</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"\"SpecialUse\" төрөлтэй нүүрэн талын үйлчилгээг ажиллуулах"</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Аппад \"specialUse\" төрөлтэй нүүрэн талын үйлчилгээнүүдийг ашиглахыг зөвшөөрнө"</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"апп сангийн хэмжээг хэмжих"</string> @@ -636,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Дэлгэцийн түгжээг ашиглах"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Үргэлжлүүлэхийн тулд дэлгэцийн түгжээгээ оруулна уу"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Мэдрэгч дээр чанга дарна уу"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Хурууны хээг таньсангүй. Дахин оролдоно уу."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Хурууны хээ мэдрэгчийг цэвэрлээд, дахин оролдоно уу"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Мэдрэгчийг цэвэрлээд, дахин оролдоно уу"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Мэдрэгч дээр чанга дарна уу"</string> @@ -701,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"Таны царай харагдахгүй байна. Утсаа нүднийхээ түвшинд барина уу."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Хэт их хөдөлгөөнтэй байна. Утсаа хөдөлгөөнгүй барина уу."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Нүүрээ дахин бүртгүүлнэ үү."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"Царайг таньсангүй. Дахин оролдоно уу."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Толгойныхоо байрлалыг бага зэрэг өөрчилнө үү"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Утас руугаа аль болох эгц харна уу"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Утас руугаа аль болох эгц харна уу"</string> diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml index 51752e33df7b..4e55d1cd7c0d 100644 --- a/core/res/res/values-mr/strings.xml +++ b/core/res/res/values-mr/strings.xml @@ -434,10 +434,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"\"systemExempted\" प्रकारासोबत अॅपला फोरग्राउंड सेवांचा वापर करण्याची अनुमती देते"</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"\"fileManagement\" प्रकारासोबत फोरग्राउंड सेवा रन करा"</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"\"fileManagement\" प्रकारासोबत अॅपला फोरग्राउंड सेवांचा वापर करण्याची अनुमती देते"</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"\"mediaProcessing\" प्रकारासह फोरग्राउंड सेवा रन करा"</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"अॅपला \"mediaProcessing\" प्रकारासह फोरग्राउंड सेवा वापरण्याची अनुमती देते"</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"\"specialUse\" प्रकारासोबत फोरग्राउंड सेवा रन करा"</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"\"specialUse\" प्रकारासोबत अॅपला फोरग्राउंड सेवांचा वापर करण्याची अनुमती देते"</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"अॅप संचयन स्थान मोजा"</string> @@ -636,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"स्क्रीन लॉक वापरा"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"पुढे सुरू ठेवण्यासाठी तुमचे स्क्रीन लॉक एंटर करा"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"सेन्सरवर जोरात प्रेस करा"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"फिंगरप्रिंट ओळखता आली नाही. पुन्हा प्रयत्न करा."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"फिंगरप्रिंट सेन्सर स्वच्छ करा आणि पुन्हा प्रयत्न करा"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"सेन्सर स्वच्छ करा आणि पुन्हा प्रयत्न करा"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"सेन्सरवर जोरात प्रेस करा"</string> @@ -701,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"तुमचा चेहरा दिसत नाही. तुमचा फोन डोळ्याच्या पातळीवर धरा."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"खूप हलत आहे. फोन स्थिर धरून ठेवा."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"कृपया तुमच्या चेहऱ्याची पुन्हा नोंदणी करा."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"चेहरा ओळखता आला नाही. पुन्हा प्रयत्न करा."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"तुमच्या डोक्याचे स्थान किंचित बदला"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"तुमच्या फोनकडे आणखी थेट पहा"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"तुमच्या फोनकडे आणखी थेट पहा"</string> diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml index 599083c277db..45e3d9182de5 100644 --- a/core/res/res/values-ms/strings.xml +++ b/core/res/res/values-ms/strings.xml @@ -434,10 +434,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Membenarkan apl menggunakan perkhidmatan latar depan dengan jenis \"systemExempted\""</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"jalankan perkhidmatan latar depan dengan jenis \"fileManagement\""</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"Benarkan apl menggunakan perkhidmatan latar depan dengan jenis \"fileManagement\""</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"jalankan perkhidmatan latar depan dengan jenis \"mediaProcessing\""</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"Membenarkan apl menggunakan perkhidmatan latar depan dengan jenis \"mediaProcessing\""</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"jalankan perkhidmatan latar depan dengan jenis \"specialUse\""</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Membenarkan apl menggunakan perkhidmatan latar depan dengan jenis \"specialUse\""</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"ukur ruang storan apl"</string> @@ -636,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Gunakan kunci skrin"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Masukkan kunci skrin untuk teruskan"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Tekan penderia dengan kuat"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Cap jari tidak dikenali. Cuba lagi."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Bersihkan penderia cap jari dan cuba lagi"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Bersihkan penderia dan cuba lagi"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Tekan penderia dengan kuat"</string> @@ -701,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"Wajah tidak kelihatan. Pegang telefon pada paras mata."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Terlalu bnyk gerakan. Pegang telefon dgn stabil."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Sila daftarkan semula wajah anda."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"Wajah tidak dikenali. Cuba lagi."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Tukar sedikit kedudukan kepala anda"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Lihat lebih lurus pada telefon"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Lihat lebih lurus pada telefon"</string> diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml index cd7d43bf92fe..6aee13e7f79c 100644 --- a/core/res/res/values-my/strings.xml +++ b/core/res/res/values-my/strings.xml @@ -434,10 +434,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"\"systemExempted\" အမျိုးအစား မျက်နှာစာဝန်ဆောင်မှုများအား အကျိုးရှိရှိ အသုံးပြုနိုင်ရန် အက်ပ်ကို ခွင့်ပြုသည်"</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"“fileManagement” အမျိုးအစား မျက်နှာစာဝန်ဆောင်မှု လုပ်ဆောင်ခြင်း"</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"“\"fileManagement” အမျိုးအစား မျက်နှာစာဝန်ဆောင်မှုများအား အကျိုးရှိရှိ အသုံးပြုနိုင်ရန် အက်ပ်ကို ခွင့်ပြုသည်"</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"“mediaProcessing” အမျိုးအစား မျက်နှာစာဝန်ဆောင်မှု လုပ်ဆောင်ခြင်း"</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"“mediaProcessing” အမျိုးအစား မျက်နှာစာဝန်ဆောင်မှုများအား အကျိုးရှိရှိ အသုံးပြုနိုင်ရန် အက်ပ်ကို ခွင့်ပြုသည်"</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"\"specialUse\" အမျိုးအစား မျက်နှာစာဝန်ဆောင်မှု လုပ်ဆောင်ခြင်း"</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"\"specialUse\" အမျိုးအစား မျက်နှာစာဝန်ဆောင်မှုများအား အကျိုးရှိရှိ အသုံးပြုနိုင်ရန် အက်ပ်ကို ခွင့်ပြုသည်"</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"အက်ပ်သိုလှောင်မှု နေရာကို တိုင်းထွာခြင်း"</string> @@ -636,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"ဖန်သားပြင်လော့ခ်ချခြင်းကို သုံးခြင်း"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"ရှေ့ဆက်ရန် သင်၏ဖန်သားပြင် လော့ခ်ချခြင်းကို ထည့်ပါ"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"အာရုံခံကိရိယာပေါ်တွင် သေချာဖိပါ"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"လက်ဗွေကို မသိရှိပါ။ ထပ်စမ်းကြည့်ပါ။"</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"လက်ဗွေ အာရုံခံကိရိယာကို သန့်ရှင်းပြီး ထပ်စမ်းကြည့်ပါ"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"အာရုံခံကိရိယာကို သန့်ရှင်းပြီး ထပ်စမ်းကြည့်ပါ"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"အာရုံခံကိရိယာပေါ်တွင် သေချာဖိပါ"</string> @@ -701,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"သင့်မျက်နှာ မမြင်ရပါ။ ဖုန်းနှင့် မျက်စိ တစ်တန်းတည်းထားပါ။"</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"လှုပ်လွန်းသည်။ ဖုန်းကို ငြိမ်ငြိမ်ကိုင်ပါ။"</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"သင့်မျက်နှာကို ပြန်စာရင်းသွင်းပါ။"</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"မျက်နှာကို မသိရှိပါ။ ထပ်စမ်းကြည့်ပါ။"</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"ခေါင်းအနေအထားကို အနည်းငယ်ပြောင်းပါ"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"သင့်ဖုန်းကို တည့်တည့်ကြည့်ပါ"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"သင့်ဖုန်းကို တည့်တည့်ကြည့်ပါ"</string> diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml index b77d86a78d1c..4965d90bc18a 100644 --- a/core/res/res/values-nb/strings.xml +++ b/core/res/res/values-nb/strings.xml @@ -434,10 +434,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Lar appen bruke forgrunnstjenester med typen «systemExempted»"</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"kjør forgrunnstjeneste med typen «fileManagement»"</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"Lar appen bruke forgrunnstjenester med typen «fileManagement»"</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"kjør forgrunnstjeneste med typen «mediaProcessing»"</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"Lar appen bruke forgrunnstjenester med typen «mediaProcessing»"</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"kjøre forgrunnstjeneste med typen «specialUse»"</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Lar appen bruke forgrunnstjenester med typen «specialUse»"</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"måle lagringsplass for apper"</string> @@ -636,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Bruk skjermlås"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Skriv inn skjermlåsen for å fortsette"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Trykk godt på sensoren"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Fingeravtrykket ble ikke gjenkjent. Prøv på nytt."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Rengjør fingeravtrykkssensoren og prøv igjen"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Rengjør sensoren og prøv igjen"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Trykk godt på sensoren"</string> @@ -701,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"Kan ikke se ansiktet ditt. Hold telefonen i øyehøyde."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"For mye bevegelse. Hold telefonen stødig."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Registrer ansiktet ditt på nytt."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"Ansiktet ble ikke gjenkjent. Prøv på nytt."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Endre hodeposisjonen litt"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Se mer direkte på telefonen"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Se mer direkte på telefonen"</string> diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml index 6dbeb402c0f4..739227647157 100644 --- a/core/res/res/values-ne/strings.xml +++ b/core/res/res/values-ne/strings.xml @@ -434,10 +434,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"यसले एपलाई \"systemExempted\" सँग सम्बन्धित फोरग्राउन्ड सेवाहरू प्रयोग गर्ने अनुमति दिन्छ"</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"यस प्रकारको \"fileManagement\" सँग सम्बन्धित फोरग्राउन्ड सेवाहरू चलाउने अनुमति"</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"यसले यो एपलाई यस प्रकारको \"fileManagement\" सँग सम्बन्धित फोरग्राउन्ड सेवाहरू प्रयोग गर्ने अनुमति दिन्छ"</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"यस प्रकारको \"mediaProcessing\" सँग सम्बन्धित फोरग्राउन्ड सेवाहरू चलाउने अनुमति"</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"यसले एपलाई यस प्रकारको \"mediaProcessing\" सँग सम्बन्धित फोरग्राउन्ड सेवाहरू प्रयोग गर्ने अनुमति दिन्छ"</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"\"specialUse\" सँग सम्बन्धित फोरग्राउन्ड सेवाहरू प्रयोग गर्ने अनुमति दिनुहोस्"</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"यसले एपलाई \"specialUse\" सँग सम्बन्धित फोरग्राउन्ड सेवाहरू प्रयोग गर्ने अनुमति दिन्छ"</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"एप भण्डारण ठाउँको मापन गर्नुहोस्"</string> @@ -636,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"स्क्रिन लक प्रयोग गर्नुहोस्"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"जारी राख्न आफ्नो स्क्रिन लक हाल्नुहोस्"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"सेन्सरमा बेसरी थिच्नुहोस्"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"फिंगरप्रिन्ट पहिचान गर्न सकिएन। फेरि प्रयास गर्नुहोस्।"</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"फिंगरप्रिन्ट सेन्सर सफा गरेर फेरि प्रयास गर्नुहोस्"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"सेन्सर सफा गरेर फेरि प्रयास गर्नुहोस्"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"सेन्सरमा बेसरी थिच्नुहोस्"</string> @@ -701,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"तपाईंको अनुहार देखिएन। तपाईंको फोन आफ्नो आँखाअघि राखी समात्नुहोस्।"</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"अत्यधिक हल्लियो। फोन स्थिर राख्नुहोस्।"</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"कृपया आफ्नो अनुहार पुनः दर्ता गर्नुहोस्।"</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"अनुहार पहिचान गर्न सकिएन। फेरि प्रयास गर्नुहोस्।"</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"आफ्नो टाउको थोरै यताउता सार्नुहोस्"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"आफ्नो फोनमा अझ सीधा हेर्नुहोस्"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"आफ्नो फोनमा अझ सीधा हेर्नुहोस्"</string> diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml index 0bd0a5937be5..dd6f3a69e46c 100644 --- a/core/res/res/values-nl/strings.xml +++ b/core/res/res/values-nl/strings.xml @@ -434,10 +434,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Hiermee kan de app gebruikmaken van services op de voorgrond van het type \'systemExempted\'"</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"service op de voorgrond van het type \'fileManagement\' uitvoeren"</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"Hiermee kan de app gebruikmaken van services op de voorgrond van het type \'fileManagement\'."</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"service op de voorgrond van het type \'mediaProcessing\' uitvoeren"</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"Hiermee kan de app gebruikmaken van services op de voorgrond van het type \'mediaProcessing\'"</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"service op de voorgrond van het type \'specialUse\' uitvoeren"</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Hiermee kan de app gebruikmaken van services op de voorgrond van het type \'specialUse\'"</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"opslagruimte van app meten"</string> @@ -636,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Schermvergrendeling gebruiken"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Voer je schermvergrendeling in om door te gaan"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Druk stevig op de sensor"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Vingerafdruk niet herkend. Probeer het opnieuw."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Reinig de vingerafdruksensor en probeer het opnieuw"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Reinig de sensor en probeer het opnieuw"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Druk stevig op de sensor"</string> @@ -701,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"Je gezicht is niet te zien. Houd je telefoon op ooghoogte."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Te veel beweging. Houd je telefoon stil."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Registreer je gezicht opnieuw."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"Gezicht niet herkend. Probeer het opnieuw."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Verander de positie van je hoofd een beetje"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Kijk goed recht naar je telefoon"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Kijk goed recht naar je telefoon"</string> diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml index 58ab2c2cbdd3..bd4653b0e775 100644 --- a/core/res/res/values-or/strings.xml +++ b/core/res/res/values-or/strings.xml @@ -434,10 +434,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"\"systemExempted\" ପ୍ରକାର ସହ ଫୋରଗ୍ରାଉଣ୍ଡ ସେବାଗୁଡ଼ିକୁ ବ୍ୟବହାର କରିବା ପାଇଁ ଆପକୁ ଅନୁମତି ଦିଏ"</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"\"fileManagement\" ପ୍ରକାର ସହ ଫୋରଗ୍ରାଉଣ୍ଡ ସେବାଗୁଡ଼ିକୁ ଚଲାଏ"</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"\"fileManagement\" ପ୍ରକାର ସହ ଫୋରଗ୍ରାଉଣ୍ଡ ସେବାଗୁଡ଼ିକୁ ବ୍ୟବହାର କରିବା ପାଇଁ ଆପକୁ ଅନୁମତି ଦିଏ"</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"\"mediaProcessing\" ପ୍ରକାର ସହ ଫୋରଗ୍ରାଉଣ୍ଡ ସେବାଗୁଡ଼ିକୁ ଚଲାଏ"</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"\"mediaProcessing\" ପ୍ରକାର ସହ ଫୋରଗ୍ରାଉଣ୍ଡ ସେବାଗୁଡ଼ିକୁ ବ୍ୟବହାର କରିବା ପାଇଁ ଆପକୁ ଅନୁମତି ଦିଏ"</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"\"specialUse\" ପ୍ରକାର ସହ ଫୋରଗ୍ରାଉଣ୍ଡ ସେବାଗୁଡ଼ିକୁ ଚଲାଏ"</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"\"specialUse\" ପ୍ରକାର ସହ ଫୋରଗ୍ରାଉଣ୍ଡ ସେବାଗୁଡ଼ିକୁ ବ୍ୟବହାର କରିବା ପାଇଁ ଆପକୁ ଅନୁମତି ଦିଏ"</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"ଆପ୍ ଷ୍ଟୋରେଜ୍ ସ୍ଥାନର ମାପ କରନ୍ତୁ"</string> @@ -636,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"ସ୍କ୍ରିନ୍ ଲକ୍ ବ୍ୟବହାର କରନ୍ତୁ"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"ଜାରି ରଖିବାକୁ ଆପଣଙ୍କ ସ୍କ୍ରିନ୍ ଲକ୍ ଏଣ୍ଟର୍ କରନ୍ତୁ"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"ସେନ୍ସର ଉପରେ ଦୃଢ଼ ଭାବେ ଦବାନ୍ତୁ"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"ଟିପଚିହ୍ନ ଚିହ୍ନଟ କରାଯାଇନାହିଁ। ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"ଟିପଚିହ୍ନ ସେନ୍ସରକୁ ପରିଷ୍କାର କରି ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"ସେନ୍ସରକୁ ପରିଷ୍କାର କରି ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"ସେନ୍ସର ଉପରେ ଦୃଢ଼ ଭାବେ ଦବାନ୍ତୁ"</string> @@ -701,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"ଆପଣଙ୍କ ଫେସ ଦେଖାଯାଉନାହିଁ। ଆପଣଙ୍କ ଫୋନକୁ ଆଖି ସିଧାରେ ଧରି ରଖନ୍ତୁ।"</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"ଅତ୍ୟଧିକ ଅସ୍ଥିର। ଫୋନ୍କୁ ସ୍ଥିର ଭାବେ ଧରନ୍ତୁ।"</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"ଦୟାକରି ଆପଣଙ୍କର ମୁହଁ ପୁଣି-ଏନ୍ରୋଲ୍ କରନ୍ତୁ।"</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"ଫେସ ଚିହ୍ନଟ କରାଯାଇନାହିଁ। ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"ଆପଣଙ୍କ ମୁଣ୍ଡର ସ୍ଥିତି ସାମାନ୍ୟ ବଦଳାନ୍ତୁ"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"ଆପଣଙ୍କ ଫୋନକୁ ସମ୍ପୂର୍ଣ୍ଣ ସିଧା ଦେଖନ୍ତୁ"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"ଆପଣଙ୍କ ଫୋନକୁ ସମ୍ପୂର୍ଣ୍ଣ ସିଧା ଦେଖନ୍ତୁ"</string> diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml index c3e4134b5325..f16234407dc0 100644 --- a/core/res/res/values-pa/strings.xml +++ b/core/res/res/values-pa/strings.xml @@ -434,10 +434,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"ਐਪ ਨੂੰ \"systemExempted\" ਕਿਸਮ ਨਾਲ ਫੋਰਗ੍ਰਾਊਂਡ ਸੇਵਾਵਾਂ ਦੀ ਵਰਤੋਂ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦੀ ਹੈ"</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"\"fileManagement\" ਕਿਸਮ ਨਾਲ ਫੋਰਗ੍ਰਾਊਂਡ ਸੇਵਾ ਨੂੰ ਚਲਾਓ"</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"ਐਪ ਨੂੰ \"fileManagement\" ਕਿਸਮ ਨਾਲ ਫੋਰਗ੍ਰਾਊਂਡ ਸੇਵਾਵਾਂ ਦੀ ਵਰਤਣ ਦੀ ਆਗਿਆ ਮਿਲਦੀ ਹੈ"</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"\"mediaProcessing\" ਕਿਸਮ ਨਾਲ ਫੋਰਗ੍ਰਾਊਂਡ ਸੇਵਾ ਨੂੰ ਚਲਾਓ"</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"ਐਪ ਨੂੰ \"mediaProcessing\" ਕਿਸਮ ਨਾਲ ਫੋਰਗ੍ਰਾਊਂਡ ਸੇਵਾਵਾਂ ਵਰਤਣ ਦੀ ਆਗਿਆ ਮਿਲਦੀ ਹੈ"</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"\"specialUse\" ਕਿਸਮ ਨਾਲ ਫੋਰਗ੍ਰਾਊਂਡ ਸੇਵਾ ਨੂੰ ਚਲਾਉਂਦੀ ਹੈ"</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"ਐਪ ਨੂੰ \"specialUse\" ਕਿਸਮ ਨਾਲ ਫੋਰਗ੍ਰਾਊਂਡ ਸੇਵਾਵਾਂ ਦੀ ਵਰਤੋਂ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦੀ ਹੈ"</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"ਐਪ ਸਟੋਰੇਜ ਜਗ੍ਹਾ ਮਾਪੋ"</string> @@ -636,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"ਸਕ੍ਰੀਨ ਲਾਕ ਦੀ ਵਰਤੋਂ ਕਰੋ"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"ਜਾਰੀ ਰੱਖਣ ਲਈ ਆਪਣਾ ਸਕ੍ਰੀਨ ਲਾਕ ਦਾਖਲ ਕਰੋ"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"ਸੈਂਸਰ ਨੂੰ ਜ਼ੋਰ ਨਾਲ ਦਬਾਓ"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਦੀ ਪਛਾਣ ਨਹੀਂ ਹੋਈ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਸੈਂਸਰ ਨੂੰ ਸਾਫ਼ ਕਰੋ ਅਤੇ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"ਸੈਂਸਰ ਨੂੰ ਸਾਫ਼ ਕਰੋ ਅਤੇ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"ਸੈਂਸਰ ਨੂੰ ਜ਼ੋਰ ਨਾਲ ਦਬਾਓ"</string> @@ -701,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"ਤੁਹਾਡਾ ਚਿਹਰਾ ਨਹੀਂ ਦਿਸ ਰਿਹਾ। ਆਪਣੇ ਫ਼ੋਨ ਨੂੰ ਅੱਖਾਂ ਦੀ ਸੀਧ ਵਿੱਚ ਰੱਖੋ।"</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"ਬਹੁਤ ਜ਼ਿਆਦਾ ਹਿਲਜੁਲ। ਫ਼ੋਨ ਨੂੰ ਸਥਿਰ ਰੱਖੋ।"</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"ਕਿਰਪਾ ਕਰਕੇ ਆਪਣਾ ਚਿਹਰਾ ਦੁਬਾਰਾ ਦਰਜ ਕਰੋ।"</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"ਚਿਹਰੇ ਦੀ ਪਛਾਣ ਨਹੀਂ ਹੋਈ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"ਆਪਣੇ ਸਿਰ ਨੂੰ ਥੋੜ੍ਹਾ ਹਿਲਾਓ"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"ਸਿੱਧਾ ਆਪਣੇ ਫ਼ੋਨ ਵੱਲ ਦੇਖੋ"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"ਸਿੱਧਾ ਆਪਣੇ ਫ਼ੋਨ ਵੱਲ ਦੇਖੋ"</string> diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml index 07a69e67fbd1..7097503f81ea 100644 --- a/core/res/res/values-pl/strings.xml +++ b/core/res/res/values-pl/strings.xml @@ -436,10 +436,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Zezwala na wykorzystywanie przez aplikację usług działających na pierwszym planie typu „systemExempted”"</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"Uruchamianie usług działających na pierwszym planie typu „fileManagement”"</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"Zezwala na wykorzystywanie przez aplikację usług działających na pierwszym planie typu „fileManagement”."</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"uruchamianie usług działających na pierwszym planie typu „mediaProcessing”"</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"Zezwala na wykorzystywanie przez aplikację usług działających na pierwszym planie typu „mediaProcessing”"</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"uruchamianie usług działających na pierwszym planie typu „specialUse”"</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Zezwala na wykorzystywanie przez aplikację usług działających na pierwszym planie typu „specialUse”"</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"mierzenie rozmiaru pamięci aplikacji"</string> @@ -638,8 +636,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Używaj blokady ekranu"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Użyj blokady ekranu, aby kontynuować"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Mocno naciśnij czujnik"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Nie rozpoznano odcisku palca. Spróbuj ponownie."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Wyczyść czytnik linii papilarnych i spróbuj ponownie"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Wyczyść czujnik i spróbuj ponownie"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Mocno naciśnij czujnik"</string> @@ -703,8 +700,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"Nie widać twarzy – trzymaj telefon na wysokości oczu"</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Telefon się porusza. Trzymaj go nieruchomo."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Zarejestruj swoją twarz ponownie."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"Nie rozpoznano twarzy. Spróbuj ponownie."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Lekko zmień położenie głowy"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Patrz prosto na telefon"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Patrz prosto na telefon"</string> diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml index e29502a61258..49b4be9eaedc 100644 --- a/core/res/res/values-pt-rBR/strings.xml +++ b/core/res/res/values-pt-rBR/strings.xml @@ -635,8 +635,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Usar bloqueio de tela"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Insira seu bloqueio de tela para continuar"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Pressione o sensor com firmeza"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Impressão digital não reconhecida. Tente de novo."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Limpe o sensor de impressão digital e tente novamente"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Limpe o sensor e tente novamente"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Pressione o sensor com firmeza"</string> @@ -700,8 +699,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"Rosto não detectado. Segure o smartphone na altura dos olhos."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Muito movimento. Não mova o smartphone."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Registre seu rosto novamente."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"Rosto não reconhecido. Tente de novo."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Mude a posição da cabeça ligeiramente"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Olhe diretamente para o smartphone"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Olhe diretamente para o smartphone"</string> diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml index cae02fcbb7b2..f5fd19f95916 100644 --- a/core/res/res/values-pt-rPT/strings.xml +++ b/core/res/res/values-pt-rPT/strings.xml @@ -635,8 +635,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Usar o bloqueio de ecrã"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Introduza o bloqueio de ecrã para continuar"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Prima firmemente o sensor"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Impressão digital não reconhecida. Tente novamente."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Limpe o sensor de impressões digitais e tente novamente"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Limpe o sensor e tente novamente"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Prima firmemente o sensor"</string> @@ -700,8 +699,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"Rosto não detetado. Segure o telemóvel ao nível dos olhos"</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Demasiado movimento. Mantenha o telemóvel firme."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Volte a inscrever o rosto."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"Rosto não reconhecido. Tente novamente."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Altere ligeiramente a posição da sua cabeça"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Olhe mais diretamente para o telemóvel"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Olhe mais diretamente para o telemóvel"</string> diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml index e29502a61258..49b4be9eaedc 100644 --- a/core/res/res/values-pt/strings.xml +++ b/core/res/res/values-pt/strings.xml @@ -635,8 +635,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Usar bloqueio de tela"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Insira seu bloqueio de tela para continuar"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Pressione o sensor com firmeza"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Impressão digital não reconhecida. Tente de novo."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Limpe o sensor de impressão digital e tente novamente"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Limpe o sensor e tente novamente"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Pressione o sensor com firmeza"</string> @@ -700,8 +699,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"Rosto não detectado. Segure o smartphone na altura dos olhos."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Muito movimento. Não mova o smartphone."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Registre seu rosto novamente."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"Rosto não reconhecido. Tente de novo."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Mude a posição da cabeça ligeiramente"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Olhe diretamente para o smartphone"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Olhe diretamente para o smartphone"</string> diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml index 2beb190c4f28..e34f9895dad8 100644 --- a/core/res/res/values-ro/strings.xml +++ b/core/res/res/values-ro/strings.xml @@ -435,10 +435,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Permite aplicației să folosească serviciile în prim-plan cu tipul „systemExempted”"</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"să folosească serviciile în prim-plan cu tipul „fileManagement”"</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"Permite aplicației să folosească serviciile în prim-plan cu tipul „fileManagement”"</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"să folosească serviciile în prim-plan cu tipul „mediaProcessing”"</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"Permite aplicației să folosească serviciile în prim-plan cu tipul „mediaProcessing”"</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"să folosească serviciile în prim-plan cu tipul „specialUse”"</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Permite aplicației să folosească serviciile în prim-plan cu tipul „specialUse”"</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"măsurare spațiu de stocare al aplicației"</string> @@ -637,8 +635,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Folosește blocarea ecranului"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Introdu blocarea ecranului pentru a continua"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Apasă ferm pe senzor"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Amprenta nu a fost recunoscută. Încearcă din nou."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Curăță senzorul de amprentă și încearcă din nou"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Curăță senzorul și încearcă din nou"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Apasă ferm pe senzor"</string> @@ -702,8 +699,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"Nu ți se vede fața. Ține telefonul la nivelul ochilor."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Prea multă mișcare. Ține telefonul nemișcat."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Reînregistrează-ți chipul."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"Fața nu a fost recunoscută. Încearcă din nou."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Schimbă ușor poziția capului"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Privește mai direct spre telefon"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Privește mai direct spre telefon"</string> diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml index 299e445799cc..d37517987545 100644 --- a/core/res/res/values-ru/strings.xml +++ b/core/res/res/values-ru/strings.xml @@ -436,10 +436,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Разрешить приложению использовать активные службы с типом systemExempted"</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"Запуск активных служб с типом fileManagement"</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"Приложение сможет использовать активные службы с типом fileManagement."</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"запускать активные службы с типом mediaProcessing"</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"Приложение сможет использовать активные службы с типом mediaProcessing."</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"запускать активные службы с типом specialUse"</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Разрешить приложению использовать активные службы с типом specialUse"</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"Вычисление объема памяти приложений"</string> @@ -638,8 +636,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Использовать блокировку экрана"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Чтобы продолжить, разблокируйте экран."</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Плотно прижмите палец к сканеру"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Отпечаток пальца не распознан. Повторите попытку."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Очистите сканер отпечатков пальцев и повторите попытку."</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Очистите сканер и повторите попытку."</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Плотно прижмите палец к сканеру."</string> @@ -703,8 +700,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"Вашего лица не видно. Держите телефон на уровне глаз"</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Не перемещайте устройство. Держите его неподвижно."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Повторите попытку."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"Лицо не распознано. Повторите попытку."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Немного измените положение головы"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Смотрите прямо на телефон"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Смотрите прямо на телефон"</string> diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml index e19231e42d52..c62fe33293ae 100644 --- a/core/res/res/values-si/strings.xml +++ b/core/res/res/values-si/strings.xml @@ -434,10 +434,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"\"systemExempted\" වර්ගය සමග පෙරබිම් සේවා භාවිතා කිරීමට යෙදුමට ඉඩ දෙයි"</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"\"fileManagement\" වර්ගය සමග පෙරබිම් සේවාව ධාවනය කරන්න"</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"\"fileManagement\" වර්ගය සමග පෙරබිම් සේවා භාවිතා කිරීමට යෙදුමට ඉඩ දෙයි"</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"\"mediaProcessing\" වර්ගය සමග පෙරබිම් සේවාව ධාවනය කරන්න"</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"\"mediaProcessing\" වර්ගය සමග පෙරබිම් සේවා භාවිතා කිරීමට යෙදුමට ඉඩ දෙයි"</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"\"specialUse\" වර්ගය සමග පෙරබිම් සේවාව ධාවනය කරන්න"</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"\"specialUse\" වර්ගය සමග පෙරබිම් සේවා භාවිතා කිරීමට යෙදුමට ඉඩ දෙයි"</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"යෙදුම් ආචයනයේ ඉඩ ප්රමාණය මැනීම"</string> @@ -636,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"තිර අගුල භාවිත කරන්න"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"ඉදිරියට යාමට ඔබගේ තිර අගුල ඇතුළත් කරන්න"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"සංවේදකය මත තදින් ඔබන්න"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"ඇඟිලි සලකුණ හඳුනා නොගැනිණි. නැවත උත්සාහ කරන්න."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"ඇඟිලි සලකුණු සංවේදකය පිරිසිදු කර නැවත උත්සාහ කරන්න"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"සංවේදකය පිරිසිදු කර නැවත උත්සාහ කරන්න"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"සංවේදකය මත තදින් ඔබන්න"</string> @@ -701,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"ඔබගේ මුහුණ දැකිය නොහැකිය. ඔබගේ දුරකථනය ඇස් මට්ටමින් අල්ලා ගන්න."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"චලනය ඉතා වැඩියි. දුරකථනය ස්ථිරව අල්ලා සිටින්න."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"ඔබේ මුහුණ යළි ලියාපදිංචි කරන්න."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"මුහුණ හඳුනා නොගැනිණි. නැවත උත්සාහ කරන්න."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"ඔබගේ හිසෙහි පිහිටීම මදක් වෙනස් කරන්න"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"ඔබගේ දුරකථනය දෙස වඩාත් ඍජුව බලන්න"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"ඔබගේ දුරකථනය දෙස වඩාත් ඍජුව බලන්න"</string> diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml index c9508ba8a7f3..61ad94de3b3a 100644 --- a/core/res/res/values-sk/strings.xml +++ b/core/res/res/values-sk/strings.xml @@ -436,10 +436,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Umožňuje aplikácii využívať služby na popredí s typom dataSync systemExempted"</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"spúšťať službu na popredí s typom remoteMessaging"</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"Umožňuje aplikácii využívať služby na popredí s typom fileManagement"</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"spúšťať službu na popredí s typom mediaProcessing"</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"Umožňuje aplikácii využívať služby na popredí s typom mediaProcessing"</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"spustiť službu na popredí s typom specialUse"</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Umožňuje aplikácii využívať služby na popredí s typom specialUse"</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"zistiť veľkosť ukladacieho priestoru aplikácie"</string> @@ -638,8 +636,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Použiť zámku obrazovky"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Pokračujte zadaním zámky obrazovky"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Pevne pritlačte prst na senzor"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Odtlačok prsta nebol rozpoznaný. Skúste to znova."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Vyčistite senzor odtlačkov prstov a skúste to znova"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Vyčistite senzor a skúste to znova"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Pevne pritlačte prst na senzor"</string> @@ -703,8 +700,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"Nie je vidieť vašu tvár. Držte telefón na úrovni očí."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Priveľa pohybu. Nehýbte telefónom."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Znova zaregistrujte svoju tvár."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"Tvár nebola rozpoznaná. Skúste to znova."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Trocha zmeňte pozíciu hlavy"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Pozrite sa na telefón priamejšie"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Pozrite sa na telefón priamejšie"</string> diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml index c459fdb720df..79e0fa3e83cd 100644 --- a/core/res/res/values-sl/strings.xml +++ b/core/res/res/values-sl/strings.xml @@ -436,10 +436,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Aplikaciji dovoljuje, da uporablja storitve v ospredju vrste »systemExempted«."</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"izvajanje storitve v ospredju vrste »fileManagement«"</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"Aplikaciji dovoljuje, da uporablja storitve v ospredju vrste »fileManagement«."</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"izvajanje storitve v ospredju vrste »mediaProcessing«"</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"Aplikaciji dovoljuje, da uporablja storitve v ospredju vrste »mediaProcessing«"</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"izvajanje storitve v ospredju vrste »specialUse«"</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Aplikaciji dovoljuje, da uporablja storitve v ospredju vrste »specialUse«."</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"izračunavanje prostora za shranjevanje aplikacije"</string> @@ -638,8 +636,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Uporaba odklepanja s poverilnico"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Odklenite zaslon, če želite nadaljevati."</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Prst dobro pridržite na tipalu"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Prstni odtis ni prepoznan. Poskusite znova."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Očistite tipalo prstnih odtisov in poskusite znova."</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Očistite tipalo in poskusite znova."</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Prst dobro pridržite na tipalu"</string> @@ -703,8 +700,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"Obraz ni viden. Držite telefon v višini oči."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Preveč se premikate. Držite telefon pri miru."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Znova registrirajte svoj obraz."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"Obraz ni prepoznan. Poskusite znova."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Nekoliko spremenite položaj glave."</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Glejte bolj naravnost v telefon"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Glejte bolj naravnost v telefon"</string> diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml index a62dddb7772a..a16059149d20 100644 --- a/core/res/res/values-sq/strings.xml +++ b/core/res/res/values-sq/strings.xml @@ -434,10 +434,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Lejon që aplikacioni të përdorë shërbimet në plan të parë me llojin \"systemExempted\""</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"ekzekuto shërbimin në plan të parë me llojin \"fileManagement\""</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"Lejon aplikacionin të përdorë shërbimet në plan të parë me llojin \"fileManagement\""</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"të ekzekutojë shërbimin në plan të parë me llojin \"mediaProcessing\""</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"Lejon që aplikacioni të përdorë shërbimet në plan të parë me llojin \"mediaProcessing\""</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"të ekzekutojë shërbimin në plan të parë me llojin \"specialUse\""</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Lejon që aplikacioni të përdorë shërbimet në plan të parë me llojin \"specialUse\""</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"mat hapësirën ruajtëse të aplikacionit"</string> @@ -636,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Përdor kyçjen e ekranit"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Fut kyçjen e ekranit për të vazhduar"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Shtyp fort te sensori"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Gjurma e gishtit nuk njihet. Provo përsëri."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Pastro sensorin e gjurmës së gishtit dhe provo sërish"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Pastro sensorin dhe provo sërish"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Shtyp fort te sensori"</string> @@ -701,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"Fytyra s\'mund të shihet. Mbaje telefonin në nivelin e syve."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Ka shumë lëvizje. Mbaje telefonin të palëvizur."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Regjistroje përsëri fytyrën tënde."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"Fytyra nuk njihet. Provo përsëri."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Ndrysho pak pozicionin e kokës"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Shiko më drejtpërdrejt telefonin"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Shiko më drejtpërdrejt telefonin"</string> diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml index 048d826adbff..e1f06de4dcfa 100644 --- a/core/res/res/values-sr/strings.xml +++ b/core/res/res/values-sr/strings.xml @@ -435,10 +435,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Дозвољава апликацији да користи услуге у првом плану које припадају типу „systemExempted“"</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"покретање услуге у првом плану која припада типу „fileManagement“"</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"Дозвољава апликацији да користи услуге у првом плану које припадају типу „fileManagement“"</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"покретање услуге у првом плану која припада типу „mediaProcessing“"</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"Дозвољава апликацији да користи услуге у првом плану које припадају типу „mediaProcessing“"</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"покретање услуге у првом плану која припада типу „specialUse“"</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Дозвољава апликацији да користи услуге у првом плану које припадају типу „specialUse“"</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"мерење меморијског простора у апликацији"</string> @@ -637,8 +635,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Користите закључавање екрана"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Употребите закључавање екрана да бисте наставили"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Чврсто притисните сензор"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Отисак прста није препознат. Пробајте поново."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Обришите сензор за отисак прста и пробајте поново"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Обришите сензор и пробајте поново"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Чврсто притисните сензор"</string> @@ -702,8 +699,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"Не види се лице. Држите телефон у висини очију."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Много се померате. Држите телефон мирно."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Поново региструјте лице."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"Лице није препознато. Пробајте поново."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Мало померите главу"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Гледајте право у телефон"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Гледајте право у телефон"</string> diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml index d10cbe6a1de1..dc9c19487266 100644 --- a/core/res/res/values-sv/strings.xml +++ b/core/res/res/values-sv/strings.xml @@ -434,10 +434,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Tillåter att appen använder förgrundstjänster av typen systemExempted"</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"kör förgrundstjänst av typen fileManagement"</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"Tillåter att appen använder förgrundstjänster av typen fileManagement"</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"kör förgrundstjänst av typen mediaProcessing"</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"Tillåter att appen använder förgrundstjänster av typen mediaProcessing"</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"kör förgrundstjänst av typen specialUse"</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Tillåter att appen använder förgrundstjänster av typen specialUse"</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"mäta appens lagringsplats"</string> @@ -636,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Använd skärmlåset"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Fortsätt med hjälp av ditt skärmlås"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Tryck hårt på sensorn"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Fingeravtrycket känns inte igen. Försök igen."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Rengör fingeravtryckssensorn och försök igen"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Rengör sensorn och försök igen"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Tryck hårt på sensorn"</string> @@ -701,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"Ansiktet syns inte. Håll telefonen i ögonhöjd."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"För mycket rörelse. Håll mobilen stilla."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Registrera ansiktet på nytt."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"Ansiktet känns inte igen. Försök igen."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Rör lite på huvudet"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Titta rakt på telefonen"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Titta rakt på telefonen"</string> diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml index 8e1348fd238e..c5979ddb410b 100644 --- a/core/res/res/values-sw/strings.xml +++ b/core/res/res/values-sw/strings.xml @@ -434,10 +434,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Huruhusu programu itumie huduma zinazoonekana kwenye skrini zinazohusiana na \"systemExempted\""</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"kutekeleza huduma inayoonekana kwenye skrini inayohusiana na \"fileManagement\""</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"Huiruhusu programu itumie huduma zinazoonekana kwenye skrini zinazohusiana na \"fileManagement\""</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"kutekeleza huduma yenye aina ya \"mediaProcessing\" inayoonekana kwenye skrini"</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"Huruhusu programu kutumia huduma zenye aina ya \"mediaProcessing\" zinazoonekana kwenye skrini"</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"kutekeleza huduma inayoonekana kwenye skrini inayohusiana na \"specialUse\""</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Huruhusu programu itumie huduma zinazoonekana kwenye skrini zinazohusiana na \"specialUse\""</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"Pima nafasi ya hifadhi ya programu"</string> @@ -636,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Tumia mbinu ya kufunga skrini"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Weka mbinu yako ya kufunga skrini ili uendelee"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Bonyeza kwa uthabiti kwenye kitambuzi"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Alama ya kidole haitambuliki. Jaribu tena."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Safisha kitambua alama ya kidole kisha ujaribu tena"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Safisha kitambuzi kisha ujaribu tena"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Bonyeza kwa nguvu kwenye kitambuzi"</string> @@ -701,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"Imeshindwa kuona uso wako. Shikilia simu ikilingana na macho."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Inatikisika sana. Ishike simu iwe thabiti."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Tafadhali sajili uso wako tena."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"Uso hautambuliki. Jaribu tena."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Badilisha nafasi ya kichwa chako kidogo"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Angalia simu yako moja kwa moja"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Angalia simu yako moja kwa moja"</string> diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml index 32fb6a433c70..5017e145c7cf 100644 --- a/core/res/res/values-ta/strings.xml +++ b/core/res/res/values-ta/strings.xml @@ -434,10 +434,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"\"systemExempted\" எனும் வகையைக் கொண்ட முன்புலச் சேவைகளைப் பயன்படுத்த ஆப்ஸை அனுமதிக்கும்"</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"\"fileManagement\" எனும் வகையைக் கொண்ட முன்புலச் சேவையை இயக்குதல்"</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"\"fileManagement\" எனும் வகையைக் கொண்ட முன்புலச் சேவைகளைப் பயன்படுத்த ஆப்ஸை அனுமதிக்கும்"</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"\"mediaProcessing\" எனும் வகையைக் கொண்ட முன்புலச் சேவையை இயக்குதல்"</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"\"mediaProcessing\" எனும் வகையைக் கொண்ட முன்புலச் சேவைகளைப் பயன்படுத்த ஆப்ஸை அனுமதிக்கும்"</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"\"specialUse\" எனும் வகையைக் கொண்ட முன்புலச் சேவையை இயக்குதல்"</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"\"specialUse\" எனும் வகையைக் கொண்ட முன்புலச் சேவைகளைப் பயன்படுத்த ஆப்ஸை அனுமதிக்கும்"</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"ஆப்ஸ் சேமிப்பு இடத்தை அளவிடல்"</string> @@ -636,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"திரைப் பூட்டைப் பயன்படுத்து"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"தொடர்வதற்கு உங்கள் திரைப் பூட்டை உள்ளிடுங்கள்"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"சென்சாரின் மீது நன்றாக அழுத்தவும்"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"கைரேகையைக் கண்டறிய முடியவில்லை. மீண்டும் முயலவும்."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"கைரேகை சென்சாரைச் சுத்தம் செய்துவிட்டு மீண்டும் முயலவும்"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"சென்சாரைச் சுத்தம் செய்துவிட்டு மீண்டும் முயலவும்"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"சென்சாரின் மீது நன்றாக அழுத்தவும்"</string> @@ -701,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"முகம் சரியாகத் தெரியவில்லை. மொபைலைக் கண்களுக்கு நேராகப் பிடிக்கவும்."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"அதிகமாக அசைகிறது. மொபைலை அசைக்காமல் பிடிக்கவும்."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"உங்கள் முகத்தை மீண்டும் பதிவுசெய்யுங்கள்."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"முகத்தைக் கண்டறிய முடியவில்லை. மீண்டும் முயலவும்."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"தலையின் நிலையைச் சிறிதளவு மாற்றவும்"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"உங்கள் மொபைலை நேராகப் பார்க்கவும்"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"உங்கள் மொபைலை நேராகப் பார்க்கவும்"</string> diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml index 3f98b25eaad1..624b2c917f0a 100644 --- a/core/res/res/values-te/strings.xml +++ b/core/res/res/values-te/strings.xml @@ -634,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"స్క్రీన్ లాక్ను ఉపయోగించండి"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"కొనసాగించడానికి మీ స్క్రీన్ లాక్ను ఎంటర్ చేయండి"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"సెన్సార్ మీద గట్టిగా నొక్కండి"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"వేలిముద్ర గుర్తించబడలేదు. మళ్లీ ట్రై చేయండి."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"వేలిముద్ర సెన్సార్ను క్లీన్ చేసి, మళ్లీ ట్రై చేయండి"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"సెన్సార్ను క్లీన్ చేసి, మళ్లీ ట్రై చేయండి"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"సెన్సార్ మీద గట్టిగా నొక్కండి"</string> @@ -699,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"మీ ముఖం కనిపించడం లేదు. మీ ఫోన్ను కళ్లకు ఎదురుగా పట్టుకోండి."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"బాగా కదుపుతున్నారు. ఫోన్ను స్థిరంగా పట్టుకోండి"</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"దయచేసి మీ ముఖాన్ని మళ్లీ నమోదు చేయండి."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"ముఖం గుర్తించబడలేదు. మళ్లీ ట్రై చేయండి."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"మీ తల స్థానాన్ని కొద్దిగా మార్చండి"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"మీ ఫోన్ వైపు మరింత నేరుగా చూడండి"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"మీ ఫోన్ వైపు మరింత నేరుగా చూడండి"</string> diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml index 81fa17769c02..155598445390 100644 --- a/core/res/res/values-th/strings.xml +++ b/core/res/res/values-th/strings.xml @@ -434,10 +434,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"อนุญาตให้แอปใช้ประโยชน์จากบริการที่ทำงานอยู่เบื้องหน้าโดยมีประเภทเป็น \"ได้รับการยกเว้นจากระบบ\""</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"เรียกใช้บริการที่ทำงานอยู่เบื้องหน้าโดยมีประเภทเป็น \"การจัดการไฟล์\""</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"อนุญาตให้แอปใช้ประโยชน์จากบริการที่ทำงานอยู่เบื้องหน้าโดยมีประเภทเป็น \"การจัดการไฟล์\""</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"เรียกใช้บริการที่ทำงานอยู่เบื้องหน้าซึ่งเป็นประเภท \"ประมวลผลสื่อ\""</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"อนุญาตให้แอปใช้ประโยชน์จากบริการที่ทำงานอยู่เบื้องหน้าซึ่งเป็นประเภท \"การประมวลผลสื่อ\""</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"เรียกใช้บริการที่ทำงานอยู่เบื้องหน้าโดยมีประเภทเป็น \"การใช้งานพิเศษ\""</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"อนุญาตให้แอปใช้ประโยชน์จากบริการที่ทำงานอยู่เบื้องหน้าโดยมีประเภทเป็น \"การใช้งานพิเศษ\""</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"วัดพื้นที่เก็บข้อมูลของแอปพลิเคชัน"</string> @@ -636,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"ใช้การล็อกหน้าจอ"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"ป้อนข้อมูลการล็อกหน้าจอเพื่อดำเนินการต่อ"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"กดเซ็นเซอร์ให้แน่น"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"ไม่รู้จักลายนิ้วมือ โปรดลองอีกครั้ง"</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"ทำความสะอาดเซ็นเซอร์ลายนิ้วมือแล้วลองอีกครั้ง"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"ทำความสะอาดเซ็นเซอร์แล้วลองอีกครั้ง"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"กดเซ็นเซอร์ให้แน่น"</string> @@ -701,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"ไม่เห็นใบหน้า ถือโทรศัพท์ไว้ที่ระดับสายตา"</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"มีการเคลื่อนไหวมากเกินไป ถือโทรศัพท์นิ่งๆ"</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"โปรดลงทะเบียนใบหน้าอีกครั้ง"</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"ไม่รู้จักใบหน้า โปรดลองอีกครั้ง"</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"เปลี่ยนตำแหน่งของศีรษะเล็กน้อย"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"โปรดมองตรงมาที่โทรศัพท์"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"โปรดมองตรงมาที่โทรศัพท์"</string> diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml index 8009e0cc6584..25422a59acba 100644 --- a/core/res/res/values-tl/strings.xml +++ b/core/res/res/values-tl/strings.xml @@ -434,10 +434,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Nagbibigay-daan sa app na gamitin ang mga serbisyo sa foreground na may uring \"systemExempted\""</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"Magpatakbo ng serbisyo sa foreground na may uring \"fileManagement\""</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"Nagbibigay-daan sa app na gamitin ang mga serbisyo sa foreground na may uring \"fileManagement\""</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"magpagana ng serbisyo sa foreground na may uring \"mediaProcessing\""</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"Nagbibigay-daan sa app na gamitin ang mga serbisyo sa foreground na may uring \"mediaProcessing\""</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"magpagana ng serbisyo sa foreground na may uring \"specialUse\""</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Nagbibigay-daan sa app na gamitin ang mga serbisyo sa foreground na may uring \"specialUse\""</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"sukatin ang espasyo ng storage ng app"</string> @@ -636,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Gumamit ng lock ng screen"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Ilagay ang iyong lock ng screen para magpatuloy"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Pumindot nang madiin sa sensor"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Hindi nakilala ang fingerprint. Subukan ulit."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Linisin ang sensor para sa fingerprint at subukan ulit"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Linisin ang sensor at subukan ulit"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Pumindot nang madiin sa sensor"</string> @@ -701,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"Hindi makita ang mukha mo. Hawakan ang telepono kapantay ng mata."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Masyadong magalaw. Hawakang mabuti ang telepono."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Paki-enroll muli ang iyong mukha."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"Hindi nakilala ang mukha. Subukan ulit."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Bahagyang baguhin ang posisyon ng iyong ulo"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Tumingin nang mas direkta sa iyong telepono"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Tumingin nang mas direkta sa iyong telepono"</string> diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml index 18f46ee4f933..64a150c914af 100644 --- a/core/res/res/values-tr/strings.xml +++ b/core/res/res/values-tr/strings.xml @@ -434,10 +434,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Uygulamanın \"systemExempted\" türüyle ön plan hizmetlerini kullanmasına izin verir"</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"\"fileManagement\" türündeki ön plan hizmetini çalıştırma"</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"Uygulamanın \"fileManagement\" türündeki ön plan hizmetlerini kullanmasına izin verir."</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"\"mediaProcessing\" türündeki ön plan hizmetini çalıştırma"</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"Uygulamanın \"mediaProcessing\" türüyle ön plan hizmetlerini kullanmasına izin verir"</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"\"specialUse\" türüyle ön plan hizmetini çalıştırma"</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Uygulamanın \"specialUse\" türüyle ön plan hizmetlerini kullanmasına izin verir"</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"uygulama depolama alanını ölç"</string> @@ -636,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Ekran kilidi kullan"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Devam etmek için ekran kilidinizi girin"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Sensöre sıkıca bastırın"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Parmak izi tanınmadı. Tekrar deneyin."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Parmak izi sensörünü temizleyip tekrar deneyin"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Sensörü temizleyip tekrar deneyin"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Sensöre sıkıca bastırın"</string> @@ -701,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"Yüzünüz görünmüyor. Telefonunuzu göz hizasında tutun."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Çok fazla hareket ediyorsunuz. Telefonu sabit tutun."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Lütfen yüzünüzü yeniden kaydedin."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"Yüz tanınmadı. Tekrar deneyin."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Başınızın konumunu hafifçe değiştirin"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Telefonunuza daha doğrudan bakın"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Telefonunuza daha doğrudan bakın"</string> diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml index 88a3b2bc60f4..81fe67f86a6a 100644 --- a/core/res/res/values-uk/strings.xml +++ b/core/res/res/values-uk/strings.xml @@ -436,10 +436,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Дозволяє додатку використовувати активні сервіси типу systemExempted"</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"запускати активний сервіс типу fileManagement"</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"Дозволяє додатку використовувати активні сервіси типу fileManagement"</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"запускати сервіс типу mediaProcessing в активному режимі"</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"Дозволяє додатку використовувати активні сервіси типу mediaProcessing"</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"запускати сервіс типу specialUse в активному режимі"</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Дозволяє додатку використовувати активні сервіси типу specialUse"</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"визначати об’єм пам’яті програми"</string> @@ -638,8 +636,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Доступ розблокуванням екрана"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Щоб продовжити, введіть дані для розблокування екрана"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Міцно притисніть палець до сканера"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Відбиток пальця не розпізнано. Повторіть спробу."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Очистьте сканер відбитків пальців і повторіть спробу"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Очистьте сканер і повторіть спробу"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Міцно притисніть палець до сканера"</string> @@ -703,8 +700,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"Обличчя не видно. Утримуйте телефон на рівні очей."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Забагато рухів. Тримайте телефон нерухомо."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Повторно проскануйте обличчя."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"Обличчя не розпізнано. Повторіть спробу."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Трохи змініть положення голови"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Дивіться на телефон прямо"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Дивіться на телефон прямо"</string> diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml index 267351a05e93..59461b8b39a8 100644 --- a/core/res/res/values-ur/strings.xml +++ b/core/res/res/values-ur/strings.xml @@ -434,10 +434,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"ایپ کو \"systemExempted\" کی قسم کے ساتھ پیش منظر کی سروسز کے استعمال کی اجازت دیتی ہے"</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"\"fileManagement\" کی قسم کے ساتھ پیش منظر کی سروس چلائیں"</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"ایپ کو \"fileManagement\" کی قسم کے ساتھ پیش منظر کی سروسز کے استعمال کی اجازت دیتی ہے"</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"\"mediaProcessing\" کی قسم کے ساتھ پیش منظر کی سروس چلائیں"</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"ایپ کو \"mediaProcessing\" کی قسم کے ساتھ پیش منظر کی سروسز کے استعمال کی اجازت دیتی ہے"</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"\"specialUse\" کی قسم کے ساتھ پیش منظر کی سروس چلائیں"</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"ایپ کو \"specialUse\" کی قسم کے ساتھ پیش منظر کی سروسز کے استعمال کی اجازت دیتی ہے"</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"ایپ اسٹوریج کی جگہ کی پیمائش کریں"</string> @@ -636,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"اسکرین لاک استعمال کریں"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"جاری رکھنے کے لیے اپنا اسکرین لاک درج کریں"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"سینسر پر اچھی طرح دبائیں"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"فنگر پرنٹ کی شناخت نہیں ہو سکی۔ دوبارہ کوشش کریں۔"</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"فنگر پرنٹ سینسر صاف کریں اور دوبارہ کوشش کریں"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"سینسر صاف کریں اور دوبارہ کوشش کریں"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"سینسر پر اچھی طرح دبائیں"</string> @@ -701,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"آپ کا چہرہ دکھائی نہیں دے رہا۔ اپنے فون کو آنکھ کی سطح پر پکڑیں۔"</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"کافی حرکت ہو رہی ہے۔ فون کو مضبوطی سے پکڑیں۔"</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"براہ کرم اپنے چہرے کو دوبارہ مندرج کریں۔"</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"چہرے کی شناخت نہیں ہو سکی۔ دوبارہ کوشش کریں۔"</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"اپنے سر کی پوزیشن کو تھوڑا تبدیل کریں"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"اپنے فون کی طرف چہرے کو سیدھا رکھیں"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"اپنے فون کی طرف چہرے کو سیدھا رکھیں"</string> diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml index d739e8b3a193..9388b0f56649 100644 --- a/core/res/res/values-uz/strings.xml +++ b/core/res/res/values-uz/strings.xml @@ -434,10 +434,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Ilovaga “systemExempted” turidagi faol xizmatlardan foydalanishga ruxsat beradi"</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"“fileManagement” turidagi faol xizmatni ishga tushirish"</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"Ilovaga “fileManagement” turidagi faol xizmatlardan foydalanishga ruxsat beradi"</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"“mediaProcessing” turidagi faol xizmatni ishga tushirish"</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"Ilovaga “mediaProcessing” turidagi faol xizmatlardan foydalanishga ruxsat beradi"</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"“specialUse” turidagi faol xizmatni ishga tushirish"</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Ilovaga “specialUse” turidagi faol xizmatlardan foydalanishga ruxsat beradi"</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"ilovalar egallagan xotira joyini hisoblash"</string> @@ -636,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Ekran qulfi"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Ekran qulfini kiritish bilan davom eting"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Sensorni mahkam bosing"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Barmoq izi aniqlanmadi. Qayta urining."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Barmoq izi skanerini tozalang va qayta urining"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Sensorni tozalang va qayta urining"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Sensorni mahkam bosing"</string> @@ -701,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"Yuz koʻrinmayapti. Telefonni koʻz darajasida tuting."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Ortiqcha harakatlanmoqda. Qimirlatmasdan ushlang."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Yuzingizni qaytadan qayd qildiring."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"Yuz aniqlanmadi. Qayta urining."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Boshingiz holatini biroz oʻzgartiring"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Telefonga tik qarab turing"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Telefonga tik qarab turing"</string> diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml index 15f7f8fea88d..b9410c1fefec 100644 --- a/core/res/res/values-vi/strings.xml +++ b/core/res/res/values-vi/strings.xml @@ -434,10 +434,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Cho phép ứng dụng dùng các dịch vụ trên nền trước thuộc loại \"systemExempted\""</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"chạy dịch vụ trên nền trước thuộc loại \"fileManagement\""</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"Cho phép ứng dụng dùng các dịch vụ trên nền trước thuộc loại \"fileManagement\""</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"chạy dịch vụ trên nền trước thuộc loại \"mediaProcessing\""</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"Cho phép ứng dụng dùng các dịch vụ trên nền trước thuộc loại \"mediaProcessing\""</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"chạy dịch vụ trên nền trước thuộc loại \"specialUse\""</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Cho phép ứng dụng dùng các dịch vụ trên nền trước thuộc loại \"specialUse\""</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"đo dung lượng lưu trữ ứng dụng"</string> @@ -636,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Dùng phương thức khóa màn hình"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Hãy nhập phương thức khóa màn hình của bạn để tiếp tục"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Ấn mạnh lên cảm biến"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Không nhận dạng được vân tay. Hãy thử lại."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Hãy vệ sinh cảm biến vân tay rồi thử lại"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Vệ sinh cảm biến rồi thử lại"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Ấn mạnh lên cảm biến"</string> @@ -701,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"Không thấy khuôn mặt. Hãy cầm điện thoại ngang tầm mắt."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Thiết bị di chuyển quá nhiều. Giữ yên thiết bị."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Vui lòng đăng ký lại khuôn mặt của bạn."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"Không nhận dạng được khuôn mặt. Hãy thử lại."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Nghiêng đầu của bạn một chút"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Nhìn thẳng vào điện thoại"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Nhìn thẳng vào điện thoại"</string> diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml index 91fdc945575e..488dcc63ff0f 100644 --- a/core/res/res/values-zh-rCN/strings.xml +++ b/core/res/res/values-zh-rCN/strings.xml @@ -434,10 +434,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"允许该应用使用“systemExempted”类型的前台服务"</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"运行“fileManagement”类型的前台服务"</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"允许该应用使用“fileManagement”类型的前台服务"</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"运行“mediaProcessing”类型的前台服务"</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"允许该应用使用“mediaProcessing”类型的前台服务"</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"运行“specialUse”类型的前台服务"</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"允许该应用使用“specialUse”类型的前台服务"</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"计算应用存储空间"</string> @@ -636,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"使用屏幕锁定凭据"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"输入您的屏幕锁定凭据才能继续"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"请用力按住传感器"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"无法识别指纹。请重试。"</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"请清洁指纹传感器,然后重试"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"请清洁传感器,然后重试"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"请用力按住传感器"</string> @@ -701,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"看不到您的脸,请将手机举到与眼睛齐平的位置。"</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"摄像头过于晃动。请将手机拿稳。"</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"请重新注册您的面孔。"</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"无法识别面孔。请重试。"</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"请略微调整头部的位置"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"请尽量直视手机"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"请尽量直视手机"</string> diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml index 3fe3061760d7..db117c52c6c8 100644 --- a/core/res/res/values-zh-rHK/strings.xml +++ b/core/res/res/values-zh-rHK/strings.xml @@ -434,10 +434,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"允許應用程式配搭「systemExempted」類型使用前景服務"</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"配搭「fileManagement」類型執行前景服務"</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"允許應用程式配搭「fileManagement」類型使用前景服務"</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"執行「mediaProcessing」類型的前景服務"</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"允許應用程式使用「mediaProcessing」類型的前景服務"</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"配搭「specialUse」類型執行前景服務"</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"允許應用程式配搭「specialUse」類型使用前景服務"</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"測量應用程式儲存空間"</string> @@ -636,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"使用螢幕鎖定"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"如要繼續操作,請輸入螢幕鎖定解鎖憑證"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"請用力按住感應器"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"無法辨識指紋,請再試一次。"</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"請清潔指紋感應器,然後再試一次"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"請清潔感應器,然後再試一次"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"請用力按住感應器"</string> @@ -701,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"看不到面孔,請將手機放在視線水平。"</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"裝置不夠穩定。請拿穩手機。"</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"請重新註冊面孔。"</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"無法辨識面孔,請再試一次。"</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"請稍為轉換頭部的位置"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"正面望向手機"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"正面望向手機"</string> diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml index 4f6ef2857981..e91dc76e2464 100644 --- a/core/res/res/values-zh-rTW/strings.xml +++ b/core/res/res/values-zh-rTW/strings.xml @@ -434,10 +434,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"允許應用程式搭配「systemExempted」類型使用前景服務"</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"搭配「fileManagement」類型執行前景服務"</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"允許應用程式搭配「fileManagement」類型使用前景服務"</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"執行「mediaProcessing」類型的前景服務"</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"允許應用程式使用「mediaProcessing」類型的前景服務"</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"搭配「specialUse」類型執行前景服務"</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"允許應用程式搭配「specialUse」類型使用前景服務"</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"測量應用程式儲存空間"</string> @@ -636,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"使用螢幕鎖定功能"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"如要繼續操作,請輸入螢幕鎖定憑證"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"請確實按住感應器"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"無法辨識指紋,請再試一次。"</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"請清潔指紋感應器,然後再試一次"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"清潔感應器,然後再試一次"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"請確實按住感應器"</string> @@ -701,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"未偵測到你的臉,請將手機舉到與眼睛同高的位置。"</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"鏡頭過度晃動,請拿穩手機。"</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"請重新註冊你的臉孔。"</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"無法辨識臉孔,請再試一次。"</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"請稍微改變頭部位置"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"請盡可能直視手機"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"請盡可能直視手機"</string> @@ -1513,10 +1509,10 @@ <string name="vpn_title_long" msgid="6834144390504619998">"<xliff:g id="APP">%s</xliff:g> 已啟用 VPN"</string> <string name="vpn_text" msgid="2275388920267251078">"輕觸一下即可管理網路。"</string> <string name="vpn_text_long" msgid="278540576806169831">"已連線至 <xliff:g id="SESSION">%s</xliff:g>,輕觸一下即可管理網路。"</string> - <string name="vpn_lockdown_connecting" msgid="6096725311950342607">"正在連線至永久連線的 VPN…"</string> - <string name="vpn_lockdown_connected" msgid="2853127976590658469">"已連線至永久連線的 VPN"</string> - <string name="vpn_lockdown_disconnected" msgid="5573611651300764955">"已中斷連線至永久連線的 VPN"</string> - <string name="vpn_lockdown_error" msgid="4453048646854247947">"無法連上永久連線的 VPN"</string> + <string name="vpn_lockdown_connecting" msgid="6096725311950342607">"正在連線至永久連線 VPN…"</string> + <string name="vpn_lockdown_connected" msgid="2853127976590658469">"已連線至永久連線 VPN"</string> + <string name="vpn_lockdown_disconnected" msgid="5573611651300764955">"已中斷連線至永久連線 VPN"</string> + <string name="vpn_lockdown_error" msgid="4453048646854247947">"無法連上永久連線 VPN"</string> <string name="vpn_lockdown_config" msgid="8331697329868252169">"變更網路或 VPN 設定"</string> <string name="upload_file" msgid="8651942222301634271">"選擇檔案"</string> <string name="no_file_chosen" msgid="4146295695162318057">"未選擇任何檔案"</string> diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml index d5ce2adc8093..87a25ca3f660 100644 --- a/core/res/res/values-zu/strings.xml +++ b/core/res/res/values-zu/strings.xml @@ -434,10 +434,8 @@ <string name="permdesc_foregroundServiceSystemExempted" msgid="947381760834649622">"Kuvumela i-app ukusebenzisa amasevisi aphambili ngohlobo lokuthi \"systemExempted\""</string> <string name="permlab_foregroundServiceFileManagement" msgid="2585000987966045030">"qalisa isevisi ephambili ngohlobo lokuthi \"Ikholi yefoni\""</string> <string name="permdesc_foregroundServiceFileManagement" msgid="417103601269698508">"Kuvumela i-app ukusebenzisa amasevisi aphambili ngohlobo lwe-\"systemExempted\""</string> - <!-- no translation found for permlab_foregroundServiceMediaProcessing (3045295152245381864) --> - <skip /> - <!-- no translation found for permdesc_foregroundServiceMediaProcessing (8303086172106677312) --> - <skip /> + <string name="permlab_foregroundServiceMediaProcessing" msgid="3045295152245381864">"qalisa isevisi ephambili ngohlobo oluthi \"mediaProcessing\""</string> + <string name="permdesc_foregroundServiceMediaProcessing" msgid="8303086172106677312">"Ivumela i-app ukusebenzisa amasevisi aphambili ngohlobo lwe-\"mediaProcessing\""</string> <string name="permlab_foregroundServiceSpecialUse" msgid="7973536745876645082">"qalisa isevisi ephambili ngohlobo lokuthi \"specialUse\""</string> <string name="permdesc_foregroundServiceSpecialUse" msgid="646713654541885919">"Kuvumela i-app ukusebenzisa amasevisi aphambili ngohlobo lokuthi \"specialUse\""</string> <string name="permlab_getPackageSize" msgid="375391550792886641">"linganisa isikhala sokugcina uhlelo lokusebenza"</string> @@ -636,8 +634,7 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Sebenzisa isikhiya sesikrini"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Faka ukukhiya isikrini kwakho ukuze uqhubeke"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Cindezela inzwa uqinise"</string> - <!-- no translation found for fingerprint_acquired_insufficient (2410176550915730974) --> - <skip /> + <string name="fingerprint_acquired_insufficient" msgid="2410176550915730974">"Isigxivizo somunwe asaziwa. Zama futhi."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Hlanza inzwa yesigxivizo somunwe bese uzame futhi"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Hlanza inzwa bese uzame futhi"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Cindezela inzwa uqinise"</string> @@ -701,8 +698,7 @@ <string name="face_acquired_not_detected" msgid="1057966913397548150">"Ayikwazi ukubona ubuso bakho. Bamba ifoni yakho iqondane namehlo"</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Ukunyakaza okuningi kakhulu. Bamba ifoni iqine."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Sicela uphinde ubhalise ubuso bakho."</string> - <!-- no translation found for face_acquired_too_different (4505278456634706967) --> - <skip /> + <string name="face_acquired_too_different" msgid="4505278456634706967">"Ubuso abaziwa. Zama futhi."</string> <string name="face_acquired_too_similar" msgid="8882920552674125694">"Shintsha indawo yekhanda lakho kancane"</string> <string name="face_acquired_pan_too_extreme" msgid="5417928604710621088">"Bheka ngqo kakhulu kufoni yakho"</string> <string name="face_acquired_tilt_too_extreme" msgid="5715715666540716620">"Bheka ngqo kakhulu kufoni yakho"</string> diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index 29086a452ee6..35276bf8ead2 100644 --- a/core/res/res/values/attrs_manifest.xml +++ b/core/res/res/values/attrs_manifest.xml @@ -506,6 +506,12 @@ receivers, and providers; it can not be used with activities. --> <attr name="singleUser" format="boolean" /> + <!-- If set to true, only a single instance of this component will + run and be available for the SYSTEM user. Non SYSTEM users will not be + allowed to access the component if this flag is enabled. + This flag can be used with services, receivers, providers and activities. --> + <attr name="systemUserOnly" format="boolean" /> + <!-- Specify a specific process that the associated code is to run in. Use with the application tag (to supply a default process for all application components), or with the activity, receiver, service, @@ -2865,6 +2871,7 @@ Context.createAttributionContext() using the first attribution tag contained here. --> <attr name="attributionTags" /> + <attr name="systemUserOnly" format="boolean" /> </declare-styleable> <!-- Attributes that can be supplied in an AndroidManifest.xml @@ -3023,6 +3030,7 @@ ignored when the process is bound into a shared isolated process by a client. --> <attr name="allowSharedIsolatedProcess" format="boolean" /> + <attr name="systemUserOnly" format="boolean" /> </declare-styleable> <!-- @hide The <code>apex-system-service</code> tag declares an apex system service @@ -3150,7 +3158,7 @@ <attr name="uiOptions" /> <attr name="parentActivityName" /> <attr name="singleUser" /> - <!-- @hide This broadcast receiver or activity will only receive broadcasts for the + <!-- This broadcast receiver or activity will only receive broadcasts for the system user--> <attr name="systemUserOnly" format="boolean" /> <attr name="persistableMode" /> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 5be29a6d68b8..5e2aacdb24af 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -57,6 +57,7 @@ <item><xliff:g id="id">@string/status_bar_screen_record</xliff:g></item> <item><xliff:g id="id">@string/status_bar_cast</xliff:g></item> <item><xliff:g id="id">@string/status_bar_ethernet</xliff:g></item> + <item><xliff:g id="id">@string/status_bar_oem_satellite</xliff:g></item> <item><xliff:g id="id">@string/status_bar_wifi</xliff:g></item> <item><xliff:g id="id">@string/status_bar_hotspot</xliff:g></item> <item><xliff:g id="id">@string/status_bar_mobile</xliff:g></item> @@ -102,6 +103,7 @@ <string translatable="false" name="status_bar_call_strength">call_strength</string> <string translatable="false" name="status_bar_sensors_off">sensors_off</string> <string translatable="false" name="status_bar_screen_record">screen_record</string> + <string translatable="false" name="status_bar_oem_satellite">satellite</string> <!-- Flag indicating whether the surface flinger has limited alpha compositing functionality in hardware. If set, the window @@ -4495,6 +4497,16 @@ <!-- URI for default Accessibility notification sound when to enable accessibility shortcut. --> <string name="config_defaultAccessibilityNotificationSound" translatable="false"></string> + <!-- Array of component names, each flattened to a string, for accessibility services that + can be enabled by the user without showing a warning prompt. These services must be + preinstalled. --> + <string-array translatable="false" name="config_trustedAccessibilityServices"> + <!-- + <item>com.example.package.first/com.example.class.FirstService</item> + <item>com.example.package.second/com.example.class.SecondService</item> + --> + </string-array> + <!-- Warning: This API can be dangerous when not implemented properly. In particular, escrow token must NOT be retrievable from device storage. In other words, either escrow token is not stored on device or its ciphertext is stored on device while @@ -5334,20 +5346,19 @@ and a second time clipped to the fill level to indicate charge --> <bool name="config_batterymeterDualTone">false</bool> - <!-- The default refresh rate for a given device. Change this value to set a higher default - refresh rate. If the hardware composer on the device supports display modes with a higher - refresh rate than the default value specified here, the framework may use those higher - refresh rate modes if an app chooses one by setting preferredDisplayModeId or calling - setFrameRate(). - If a non-zero value is set for config_defaultPeakRefreshRate, then - config_defaultRefreshRate may be set to 0, in which case the value set for - config_defaultPeakRefreshRate will act as the default frame rate. --> - <integer name="config_defaultRefreshRate">60</integer> - - <!-- The default peak refresh rate for a given device. Change this value if you want to prevent - the framework from using higher refresh rates, even if display modes with higher refresh - rates are available from hardware composer. Only has an effect if the value is - non-zero. --> + <!-- The default refresh rate for a given device. This value is used to set the + global refresh rate vote, and when set to zero it has no effect on the vote. + If this value is non-zero but the hardware composer on the device supports + display modes with higher refresh rates, the framework may use those higher + refresh rate modes if an app chooses one by setting preferredDisplayModeId + or calling setFrameRate().--> + <integer name="config_defaultRefreshRate">0</integer> + + <!-- The default peak refresh rate for a given device. This value is used to set the + global peak refresh rate vote, and when set to zero it has no effect on the vote. + Change this value to non-zero if you want to prevent the framework from using higher + refresh rates, even if display modes with higher refresh rates are available from + hardware composer. --> <integer name="config_defaultPeakRefreshRate">0</integer> <!-- External display peak refresh rate for the given device. Change this value if you want to @@ -6890,4 +6901,8 @@ <!-- Defines suitability of the built-in speaker route. Refer to {@link MediaRoute2Info} to see supported values. --> <integer name="config_mediaRouter_builtInSpeakerSuitability">0</integer> + + <!-- Whether to show a percentage text next to the progressbar while preparing to update the + device --> + <bool name="config_showPercentageTextDuringRebootToUpdate">true</bool> </resources> diff --git a/core/res/res/values/public-staging.xml b/core/res/res/values/public-staging.xml index 7d2288599841..b8fc052a2fa9 100644 --- a/core/res/res/values/public-staging.xml +++ b/core/res/res/values/public-staging.xml @@ -121,6 +121,8 @@ <public name="adServiceTypes" /> <!-- @hide @SystemApi @FlaggedApi("android.content.res.manifest_flagging") --> <public name="featureFlag"/> + <!-- @FlaggedApi("android.multiuser.enable_system_user_only_for_services_and_providers") --> + <public name="systemUserOnly"/> </staging-public-group> <staging-public-group type="id" first-id="0x01bc0000"> diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml index 619ec31e37bc..22d028cb079e 100644 --- a/core/res/res/values/styles.xml +++ b/core/res/res/values/styles.xml @@ -1515,6 +1515,11 @@ please see styles_device_defaults.xml. <item name="background">@drawable/btn_outlined</item> </style> + <!-- @hide Divider for Autofill half screen dialog --> + <style name="AutofillHalfSheetDivider"> + <item name="android:background">@drawable/autofill_half_sheet_divider</item> + </style> + <!-- @hide Autofill background for popup window (not for fullscreen) --> <style name="AutofillDatasetPicker"> <item name="elevation">4dp</item> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index d12ef2b95f06..33ea02ac8172 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -3198,6 +3198,7 @@ <java-symbol type="string" name="status_bar_camera" /> <java-symbol type="string" name="status_bar_sensors_off" /> <java-symbol type="string" name="status_bar_screen_record" /> + <java-symbol type="string" name="status_bar_oem_satellite" /> <!-- Locale picker --> <java-symbol type="id" name="locale_search_menu" /> @@ -3629,6 +3630,7 @@ <java-symbol type="string" name="config_defaultAccessibilityService" /> <java-symbol type="string" name="config_defaultAccessibilityNotificationSound" /> <java-symbol type="string" name="accessibility_shortcut_spoken_feedback" /> + <java-symbol type="array" name="config_trustedAccessibilityServices" /> <java-symbol type="string" name="accessibility_select_shortcut_menu_title" /> <java-symbol type="string" name="accessibility_edit_shortcut_menu_button_title" /> @@ -3702,6 +3704,10 @@ <java-symbol type="id" name="autofill_dataset_list"/> <java-symbol type="id" name="autofill_dataset_picker"/> <java-symbol type="id" name="autofill_dataset_title" /> + <java-symbol type="id" name="autofill_sheet_divider"/> + <java-symbol type="id" name="autofill_sheet_scroll_view"/> + <java-symbol type="id" name="autofill_sheet_scroll_view_space"/> + <java-symbol type="id" name="autofill_save_custom_subtitle" /> <java-symbol type="id" name="autofill_save_icon" /> <java-symbol type="id" name="autofill_save_no" /> @@ -5311,4 +5317,7 @@ <!-- Android MediaRouter framework configs. --> <java-symbol type="integer" name="config_mediaRouter_builtInSpeakerSuitability" /> + + <!-- Shutdown thread config flags --> + <java-symbol type="bool" name="config_showPercentageTextDuringRebootToUpdate" /> </resources> diff --git a/core/tests/BroadcastRadioTests/src/android/hardware/radio/RadioManagerTest.java b/core/tests/BroadcastRadioTests/src/android/hardware/radio/RadioManagerTest.java index bbac69f35e81..4f9b2697ee89 100644 --- a/core/tests/BroadcastRadioTests/src/android/hardware/radio/RadioManagerTest.java +++ b/core/tests/BroadcastRadioTests/src/android/hardware/radio/RadioManagerTest.java @@ -23,6 +23,7 @@ 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.doThrow; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -728,10 +729,10 @@ public final class RadioManagerTest { @Test public void equals_withFmBandConfigsOfDifferentAfSupportValues() { - RadioManager.FmBandConfig fmBandConfigCompared = new RadioManager.FmBandConfig( - new RadioManager.FmBandDescriptor(REGION, RadioManager.BAND_FM, FM_LOWER_LIMIT, - FM_UPPER_LIMIT, FM_SPACING, STEREO_SUPPORTED, RDS_SUPPORTED, TA_SUPPORTED, - !AF_SUPPORTED, EA_SUPPORTED)); + RadioManager.FmBandConfig.Builder builder = new RadioManager.FmBandConfig.Builder( + createFmBandDescriptor()).setStereo(STEREO_SUPPORTED).setRds(RDS_SUPPORTED) + .setTa(TA_SUPPORTED).setAf(!AF_SUPPORTED).setEa(EA_SUPPORTED); + RadioManager.FmBandConfig fmBandConfigCompared = builder.build(); assertWithMessage("FM Band Config of different af support value") .that(FM_BAND_CONFIG).isNotEqualTo(fmBandConfigCompared); @@ -1300,6 +1301,18 @@ public final class RadioManagerTest { } @Test + public void addAnnouncementListener_withListenerAddedBeforeAndCloseException_throws() + throws Exception { + createRadioManager(); + Set<Integer> enableTypeSet = createAnnouncementTypeSet(EVENT_ANNOUNCEMENT_TYPE); + mRadioManager.addAnnouncementListener(enableTypeSet, mEventListener); + doThrow(new RemoteException()).when(mCloseHandleMock).close(); + + assertThrows(RuntimeException.class, + () -> mRadioManager.addAnnouncementListener(enableTypeSet, mEventListener)); + } + + @Test public void addAnnouncementListener_whenServiceDied_throwException() throws Exception { createRadioManager(); String exceptionMessage = "service is dead"; diff --git a/core/tests/BroadcastRadioTests/src/android/hardware/radio/TunerAdapterTest.java b/core/tests/BroadcastRadioTests/src/android/hardware/radio/TunerAdapterTest.java index 4841711f712d..4cda26de2906 100644 --- a/core/tests/BroadcastRadioTests/src/android/hardware/radio/TunerAdapterTest.java +++ b/core/tests/BroadcastRadioTests/src/android/hardware/radio/TunerAdapterTest.java @@ -125,6 +125,16 @@ public final class TunerAdapterTest { } @Test + public void close_forTunerAdapterCalledTwice() throws Exception { + mRadioTuner.close(); + verify(mTunerMock).close(); + + mRadioTuner.close(); + + verify(mTunerMock).close(); + } + + @Test public void setConfiguration_forTunerAdapter() throws Exception { int status = mRadioTuner.setConfiguration(TEST_BAND_CONFIG); @@ -134,6 +144,12 @@ public final class TunerAdapterTest { } @Test + public void setConfiguration_withNull_fails() throws Exception { + assertWithMessage("Status for setting configuration with null") + .that(mRadioTuner.setConfiguration(null)).isEqualTo(RadioManager.STATUS_BAD_VALUE); + } + + @Test public void setConfiguration_withInvalidParameters_fails() throws Exception { doThrow(new IllegalArgumentException()).when(mTunerMock).setConfiguration(any()); @@ -840,6 +856,15 @@ public final class TunerAdapterTest { } @Test + public void onTuneFailed_withDeadService() throws Exception { + mTunerCallback.onTuneFailed(RadioManager.STATUS_DEAD_OBJECT, FM_SELECTOR); + + verify(mCallbackMock, timeout(CALLBACK_TIMEOUT_MS)).onTuneFailed( + RadioManager.STATUS_DEAD_OBJECT, FM_SELECTOR); + verify(mCallbackMock, timeout(CALLBACK_TIMEOUT_MS)).onError(RadioTuner.ERROR_SERVER_DIED); + } + + @Test public void onProgramListChanged_forTunerCallbackAdapter() throws Exception { mTunerCallback.onProgramListChanged(); diff --git a/core/tests/coretests/src/android/app/usage/UsageEventsQueryTest.java b/core/tests/coretests/src/android/app/usage/UsageEventsQueryTest.java index 4565978434ee..55168458d49a 100644 --- a/core/tests/coretests/src/android/app/usage/UsageEventsQueryTest.java +++ b/core/tests/coretests/src/android/app/usage/UsageEventsQueryTest.java @@ -33,6 +33,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import java.util.Random; +import java.util.Set; @RunWith(AndroidJUnit4.class) @SmallTest @@ -142,4 +143,19 @@ public class UsageEventsQueryTest { fail("Valid event type: " + eventType); } } + + @Test + @RequiresFlagsEnabled(FLAG_FILTER_BASED_EVENT_QUERY_API) + public void testQueryEventPackages() { + UsageEventsQuery.Builder queryBuilder = new UsageEventsQuery.Builder(1000, 2000); + + // Test with duplicate package names and empty package name + final String pkgName = "test.package.name"; + UsageEventsQuery query = queryBuilder.setPackageNames(pkgName, pkgName, "", pkgName) + .build(); + Set<String> pkgNameSet = query.getPackageNames(); + // Duplicated package names and empty package name will be ignored. + assertEquals(pkgNameSet.size(), 1); + assertEquals(pkgName, pkgNameSet.iterator().next()); + } } diff --git a/core/tests/coretests/src/android/database/sqlite/SQLiteDatabaseTest.java b/core/tests/coretests/src/android/database/sqlite/SQLiteDatabaseTest.java index e118c98dd4da..3ee565f8e025 100644 --- a/core/tests/coretests/src/android/database/sqlite/SQLiteDatabaseTest.java +++ b/core/tests/coretests/src/android/database/sqlite/SQLiteDatabaseTest.java @@ -403,4 +403,41 @@ public class SQLiteDatabaseTest { } assertFalse(allowed); } + + /** Return true if the path is in the list of strings. */ + private boolean isConcurrent(String path) throws Exception { + path = new File(path).toPath().toRealPath().toString(); + return SQLiteDatabase.getConcurrentDatabasePaths().contains(path); + } + + @Test + public void testDuplicateDatabases() throws Exception { + // The two database paths in this test are assumed not to have been opened earlier in this + // process. + + // A database path that will be opened twice. + final String dbName = "never-used-db.db"; + final File dbFile = mContext.getDatabasePath(dbName); + final String dbPath = dbFile.getPath(); + + // A database path that will be opened only once. + final String okName = "never-used-ok.db"; + final File okFile = mContext.getDatabasePath(okName); + final String okPath = okFile.getPath(); + + SQLiteDatabase db1 = SQLiteDatabase.openOrCreateDatabase(dbFile, null); + assertFalse(isConcurrent(dbPath)); + SQLiteDatabase db2 = SQLiteDatabase.openOrCreateDatabase(dbFile, null); + assertTrue(isConcurrent(dbPath)); + db1.close(); + assertTrue(isConcurrent(dbPath)); + db2.close(); + assertTrue(isConcurrent(dbPath)); + + SQLiteDatabase db3 = SQLiteDatabase.openOrCreateDatabase(okFile, null); + db3.close(); + db3 = SQLiteDatabase.openOrCreateDatabase(okFile, null); + assertFalse(isConcurrent(okPath)); + db3.close(); + } } diff --git a/core/tests/coretests/src/android/os/FileUtilsTest.java b/core/tests/coretests/src/android/os/FileUtilsTest.java index 60500d53292a..78a2c1c4ddbe 100644 --- a/core/tests/coretests/src/android/os/FileUtilsTest.java +++ b/core/tests/coretests/src/android/os/FileUtilsTest.java @@ -29,6 +29,7 @@ import static android.os.ParcelFileDescriptor.MODE_READ_ONLY; import static android.os.ParcelFileDescriptor.MODE_READ_WRITE; import static android.os.ParcelFileDescriptor.MODE_TRUNCATE; import static android.os.ParcelFileDescriptor.MODE_WRITE_ONLY; +import static android.system.OsConstants.AF_INET; import static android.system.OsConstants.F_OK; import static android.system.OsConstants.O_APPEND; import static android.system.OsConstants.O_CREAT; @@ -37,6 +38,7 @@ import static android.system.OsConstants.O_RDWR; import static android.system.OsConstants.O_TRUNC; import static android.system.OsConstants.O_WRONLY; import static android.system.OsConstants.R_OK; +import static android.system.OsConstants.SOCK_STREAM; import static android.system.OsConstants.W_OK; import static android.system.OsConstants.X_OK; import static android.text.format.DateUtils.DAY_IN_MILLIS; @@ -55,6 +57,7 @@ import android.os.FileUtils.MemoryPipe; import android.platform.test.annotations.IgnoreUnderRavenwood; import android.platform.test.ravenwood.RavenwoodRule; import android.provider.DocumentsContract.Document; +import android.system.Os; import android.util.DataUnit; import androidx.test.runner.AndroidJUnit4; @@ -67,6 +70,8 @@ import org.junit.runner.RunWith; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; import java.io.File; import java.io.FileDescriptor; import java.io.FileInputStream; @@ -78,6 +83,7 @@ import java.nio.file.Files; import java.util.Arrays; import java.util.HashSet; import java.util.Random; +import java.net.InetSocketAddress; @RunWith(AndroidJUnit4.class) public class FileUtilsTest { @@ -253,6 +259,84 @@ public class FileUtilsTest { assertArrayEquals(expected, actual); } + //TODO(ravenwood) Remove the _$noRavenwood suffix and add @RavenwoodIgnore instead + @Test + public void testCopy_SocketToFile_FileToSocket$noRavenwood() throws Exception { + for (int size : DATA_SIZES ) { + final File src = new File(mTarget, "src"); + final File dest = new File(mTarget, "dest"); + byte[] expected = new byte[size]; + byte[] actual = new byte[size]; + new Random().nextBytes(expected); + + // write test data in to src file + writeFile(src, expected); + + // start server, get data from client and save to dest file (socket --> file) + FileDescriptor srvSocketFd = Os.socket(AF_INET, SOCK_STREAM, 0); + Os.bind(srvSocketFd, new InetSocketAddress("localhost", 0)); + Os.listen(srvSocketFd, 5); + InetSocketAddress localSocketAddress = (InetSocketAddress) Os.getsockname(srvSocketFd); + + final Thread srv = new Thread(new Runnable() { + public void run() { + try { + InetSocketAddress peerAddress = new InetSocketAddress(); + FileDescriptor srvConnFd = Os.accept(srvSocketFd, peerAddress); + + // read file size + byte[] rcvFileSizeByteArray = new byte[8]; + Os.read(srvConnFd, rcvFileSizeByteArray, 0, rcvFileSizeByteArray.length); + long rcvFileSize = 0; + for (int i = 0; i < 8; i++) { + rcvFileSize <<= 8; + rcvFileSize |= (rcvFileSizeByteArray[i] & 0xFF); + } + + FileOutputStream fileOutputStream = new FileOutputStream(dest); + // copy data from socket to file + FileUtils.copy(srvConnFd, fileOutputStream.getFD(), rcvFileSize, null, null, null); + + fileOutputStream.close(); + Os.close(srvConnFd); + Os.close(srvSocketFd); + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + + srv.start(); + + + // start client, get data from dest file and send to server (file --> socket) + FileDescriptor clientFd = Os.socket(AF_INET, SOCK_STREAM, 0); + Os.connect(clientFd, localSocketAddress.getAddress(), localSocketAddress.getPort()); + + FileInputStream fileInputStream = new FileInputStream(src); + long sndFileSize = src.length(); + // send the file size to server + byte[] sndFileSizeByteArray = new byte[8]; + for (int i = 7; i >= 0; i--) { + sndFileSizeByteArray[i] = (byte)(sndFileSize & 0xFF); + sndFileSize >>= 8; + } + Os.write(clientFd, sndFileSizeByteArray, 0, sndFileSizeByteArray.length); + + // copy data from file to socket + FileUtils.copy(fileInputStream.getFD(), clientFd, src.length(), null, null, null); + + fileInputStream.close(); + Os.close(clientFd); + + srv.join(); + + // read test data from dest file + actual = readFile(dest); + assertArrayEquals(expected, actual); + } + } + @Test public void testIsFilenameSafe() throws Exception { assertTrue(FileUtils.isFilenameSafe(new File("foobar"))); diff --git a/core/tests/coretests/src/android/text/TextLineJustificationTest.kt b/core/tests/coretests/src/android/text/TextLineJustificationTest.kt new file mode 100644 index 000000000000..a52561557523 --- /dev/null +++ b/core/tests/coretests/src/android/text/TextLineJustificationTest.kt @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.text + +import android.platform.test.flag.junit.DeviceFlagsValueProvider +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.google.common.truth.Truth.assertThat +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith + +@SmallTest +@RunWith(AndroidJUnit4::class) +class TextLineJustificationTest { + + @Rule + @JvmField + val mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule() + + private val PAINT = TextPaint().apply { + textSize = 10f // make 1em = 10px + } + + private fun makeTextLine(cs: CharSequence, paint: TextPaint) = TextLine.obtain().apply { + set(paint, cs, 0, cs.length, Layout.DIR_LEFT_TO_RIGHT, Layout.DIRS_ALL_LEFT_TO_RIGHT, false, + null, 0, 0, false) + } + + private fun getClusterCount(cs: CharSequence, paint: TextPaint) = TextLine.LineInfo().apply { + makeTextLine(cs, paint).also { + it.metrics(null, null, false, this) + TextLine.recycle(it) + } + }.clusterCount + + fun justifyTest_WithoutJustify() { + val line = "Hello, World." + val tl = makeTextLine(line, PAINT) + + // Without calling justify method, justifying should be false and all added spaces should + // be zeros. + assertThat(tl.isJustifying).isFalse() + assertThat(tl.addedWordSpacingInPx).isEqualTo(0) + assertThat(tl.addedLetterSpacingInPx).isEqualTo(0) + } + + @Test + fun justifyTest_IntrCharacter_Latin() { + val line = "Hello, World." + val clusterCount = getClusterCount(line, PAINT) + val originalWidth = Layout.getDesiredWidth(line, PAINT) + val extraWidth = 100f + + val tl = makeTextLine(line, PAINT) + tl.justify(Layout.JUSTIFICATION_MODE_INTER_CHARACTER, originalWidth + extraWidth) + + assertThat(tl.isJustifying).isTrue() + assertThat(tl.addedWordSpacingInPx).isEqualTo(0) + assertThat(tl.addedLetterSpacingInPx).isEqualTo(extraWidth / (clusterCount - 1)) + + TextLine.recycle(tl) + } + + @Test + fun justifyTest_IntrCharacter_Japanese() { + val line = "\u672C\u65E5\u306F\u6674\u5929\u306A\u308A\u3002" + val clusterCount = getClusterCount(line, PAINT) + val originalWidth = Layout.getDesiredWidth(line, PAINT) + val extraWidth = 100f + + val tl = makeTextLine(line, PAINT) + tl.justify(Layout.JUSTIFICATION_MODE_INTER_CHARACTER, originalWidth + extraWidth) + + assertThat(tl.isJustifying).isTrue() + assertThat(tl.addedWordSpacingInPx).isEqualTo(0) + assertThat(tl.addedLetterSpacingInPx).isEqualTo(extraWidth / (clusterCount - 1)) + + TextLine.recycle(tl) + } + + @Test + fun justifyTest_IntrWord_Latin() { + val line = "Hello, World." + val originalWidth = Layout.getDesiredWidth(line, PAINT) + val extraWidth = 100f + + val tl = makeTextLine(line, PAINT) + tl.justify(Layout.JUSTIFICATION_MODE_INTER_WORD, originalWidth + extraWidth) + + assertThat(tl.isJustifying).isTrue() + // This text contains only one whitespace, so word spacing should be same to the extraWidth. + assertThat(tl.addedWordSpacingInPx).isEqualTo(extraWidth) + assertThat(tl.addedLetterSpacingInPx).isEqualTo(0) + + TextLine.recycle(tl) + } + + @Test + fun justifyTest_IntrWord_Japanese() { + val line = "\u672C\u65E5\u306F\u6674\u0020\u5929\u306A\u308A\u3002" + val originalWidth = Layout.getDesiredWidth(line, PAINT) + val extraWidth = 100f + + val tl = makeTextLine(line, PAINT) + tl.justify(Layout.JUSTIFICATION_MODE_INTER_WORD, originalWidth + extraWidth) + + assertThat(tl.isJustifying).isTrue() + // This text contains only one whitespace, so word spacing should be same to the extraWidth. + assertThat(tl.addedWordSpacingInPx).isEqualTo(extraWidth) + assertThat(tl.addedLetterSpacingInPx).isEqualTo(0) + + TextLine.recycle(tl) + } +}
\ No newline at end of file diff --git a/core/tests/coretests/src/android/text/TextLineTest.java b/core/tests/coretests/src/android/text/TextLineTest.java index a31992c8cfa1..8ae5669de55f 100644 --- a/core/tests/coretests/src/android/text/TextLineTest.java +++ b/core/tests/coretests/src/android/text/TextLineTest.java @@ -53,7 +53,7 @@ public class TextLineTest { final float originalWidth = tl.metrics(null, null, false, null); final float expandedWidth = 2 * originalWidth; - tl.justify(expandedWidth); + tl.justify(Layout.JUSTIFICATION_MODE_INTER_WORD, expandedWidth); final float newWidth = tl.metrics(null, null, false, null); TextLine.recycle(tl); return Math.abs(newWidth - expandedWidth) < 0.5; diff --git a/core/tests/coretests/src/android/view/ViewRootImplTest.java b/core/tests/coretests/src/android/view/ViewRootImplTest.java index cfbda84f24e1..cf3eb12498ca 100644 --- a/core/tests/coretests/src/android/view/ViewRootImplTest.java +++ b/core/tests/coretests/src/android/view/ViewRootImplTest.java @@ -19,7 +19,6 @@ package android.view; import static android.view.accessibility.Flags.FLAG_FORCE_INVERT_COLOR; import static android.view.flags.Flags.FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY; import static android.view.Surface.FRAME_RATE_CATEGORY_HIGH; -import static android.view.Surface.FRAME_RATE_CATEGORY_HIGH_HINT; import static android.view.Surface.FRAME_RATE_CATEGORY_LOW; import static android.view.Surface.FRAME_RATE_CATEGORY_NORMAL; import static android.view.Surface.FRAME_RATE_CATEGORY_NO_PREFERENCE; @@ -576,13 +575,8 @@ public class ViewRootImplTest { assertEquals(viewRootImpl.getPreferredFrameRateCategory(), FRAME_RATE_CATEGORY_LOW); viewRootImpl.votePreferredFrameRateCategory(FRAME_RATE_CATEGORY_NORMAL); assertEquals(viewRootImpl.getPreferredFrameRateCategory(), FRAME_RATE_CATEGORY_NORMAL); - viewRootImpl.votePreferredFrameRateCategory(FRAME_RATE_CATEGORY_HIGH_HINT); - assertEquals(viewRootImpl.getPreferredFrameRateCategory(), - FRAME_RATE_CATEGORY_HIGH_HINT); viewRootImpl.votePreferredFrameRateCategory(FRAME_RATE_CATEGORY_HIGH); assertEquals(viewRootImpl.getPreferredFrameRateCategory(), FRAME_RATE_CATEGORY_HIGH); - viewRootImpl.votePreferredFrameRateCategory(FRAME_RATE_CATEGORY_HIGH_HINT); - assertEquals(viewRootImpl.getPreferredFrameRateCategory(), FRAME_RATE_CATEGORY_HIGH); viewRootImpl.votePreferredFrameRateCategory(FRAME_RATE_CATEGORY_NORMAL); assertEquals(viewRootImpl.getPreferredFrameRateCategory(), FRAME_RATE_CATEGORY_HIGH); viewRootImpl.votePreferredFrameRateCategory(FRAME_RATE_CATEGORY_LOW); diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml index 69ad919ec979..2de305f8e925 100644 --- a/data/etc/privapp-permissions-platform.xml +++ b/data/etc/privapp-permissions-platform.xml @@ -23,40 +23,48 @@ applications that come with the platform <!-- Needed for Build.getSerial(), which is used to send a unique number for serial, per HUIG. --> <privapp-permissions package="android.car.usb.handler"> <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/> + <permission name="android.permission.READ_SYSTEM_GRAMMATICAL_GENDER"/> </privapp-permissions> <privapp-permissions package="com.android.angle"> <permission name="android.permission.WRITE_SECURE_SETTINGS"/> + <permission name="android.permission.READ_SYSTEM_GRAMMATICAL_GENDER"/> </privapp-permissions> <privapp-permissions package="com.android.apps.tag"> <permission name="android.permission.WRITE_SECURE_SETTINGS"/> + <permission name="android.permission.READ_SYSTEM_GRAMMATICAL_GENDER"/> </privapp-permissions> <privapp-permissions package="com.android.backupconfirm"> <permission name="android.permission.BACKUP"/> <permission name="android.permission.CRYPT_KEEPER"/> + <permission name="android.permission.READ_SYSTEM_GRAMMATICAL_GENDER"/> </privapp-permissions> <privapp-permissions package="com.android.externalstorage"> <permission name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> <permission name="android.permission.WRITE_MEDIA_STORAGE"/> <permission name="android.permission.MANAGE_EXTERNAL_STORAGE"/> + <permission name="android.permission.READ_SYSTEM_GRAMMATICAL_GENDER"/> </privapp-permissions> <privapp-permissions package="com.android.imsserviceentitlement"> <permission name="android.permission.MODIFY_PHONE_STATE" /> <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE" /> + <permission name="android.permission.READ_SYSTEM_GRAMMATICAL_GENDER"/> </privapp-permissions> <privapp-permissions package="com.android.launcher3"> <permission name="android.permission.WRITE_SECURE_SETTINGS"/> + <permission name="android.permission.READ_SYSTEM_GRAMMATICAL_GENDER"/> </privapp-permissions> <privapp-permissions package="com.android.location.fused"> <permission name="android.permission.INSTALL_LOCATION_PROVIDER"/> <permission name="android.permission.UPDATE_DEVICE_STATS"/> <permission name="android.permission.UPDATE_APP_OPS_STATS"/> + <permission name="android.permission.READ_SYSTEM_GRAMMATICAL_GENDER"/> </privapp-permissions> <privapp-permissions package="com.android.managedprovisioning"> @@ -79,12 +87,14 @@ applications that come with the platform <permission name="android.permission.WRITE_SECURE_SETTINGS"/> <permission name="android.permission.START_ACTIVITIES_FROM_BACKGROUND"/> <permission name="android.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND"/> + <permission name="android.permission.READ_SYSTEM_GRAMMATICAL_GENDER"/> </privapp-permissions> <privapp-permissions package="com.android.mms.service"> <permission name="android.permission.BIND_CARRIER_MESSAGING_SERVICE"/> <permission name="android.permission.BIND_CARRIER_SERVICES"/> <permission name="android.permission.INTERACT_ACROSS_USERS"/> + <permission name="android.permission.READ_SYSTEM_GRAMMATICAL_GENDER"/> </privapp-permissions> <privapp-permissions package="com.android.mtp"> @@ -94,16 +104,19 @@ applications that come with the platform <permission name="android.permission.INTERACT_ACROSS_USERS"/> <permission name="android.permission.WRITE_MEDIA_STORAGE"/> <permission name="android.permission.MANAGE_EXTERNAL_STORAGE"/> + <permission name="android.permission.READ_SYSTEM_GRAMMATICAL_GENDER"/> </privapp-permissions> <privapp-permissions package="com.android.musicfx"> <permission name="android.permission.CHANGE_COMPONENT_ENABLED_STATE"/> + <permission name="android.permission.READ_SYSTEM_GRAMMATICAL_GENDER"/> </privapp-permissions> <privapp-permissions package="com.android.networkrecommendation"> <permission name="android.permission.SCORE_NETWORKS"/> <permission name="android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME"/> <permission name="android.permission.WRITE_SECURE_SETTINGS"/> + <permission name="android.permission.READ_SYSTEM_GRAMMATICAL_GENDER"/> </privapp-permissions> <privapp-permissions package="com.android.packageinstaller"> @@ -114,6 +127,7 @@ applications that come with the platform <permission name="android.permission.UPDATE_APP_OPS_STATS"/> <permission name="android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME"/> <permission name="android.permission.PACKAGE_USAGE_STATS"/> + <permission name="android.permission.READ_SYSTEM_GRAMMATICAL_GENDER"/> </privapp-permissions> <privapp-permissions package="com.android.phone"> @@ -170,6 +184,7 @@ applications that come with the platform <permission name="android.permission.LOG_COMPAT_CHANGE"/> <permission name="android.permission.READ_COMPAT_CHANGE_CONFIG"/> <permission name="android.permission.UWB_PRIVILEGED"/> + <permission name="android.permission.READ_SYSTEM_GRAMMATICAL_GENDER"/> </privapp-permissions> <privapp-permissions package="com.android.providers.calendar"> @@ -180,6 +195,7 @@ applications that come with the platform <permission name="android.permission.USE_RESERVED_DISK"/> <permission name="android.permission.LOG_COMPAT_CHANGE" /> <permission name="android.permission.READ_COMPAT_CHANGE_CONFIG" /> + <permission name="android.permission.READ_SYSTEM_GRAMMATICAL_GENDER"/> </privapp-permissions> <privapp-permissions package="com.android.providers.contacts"> @@ -193,6 +209,7 @@ applications that come with the platform <permission name="android.permission.USE_RESERVED_DISK"/> <permission name="android.permission.READ_COMPAT_CHANGE_CONFIG" /> <permission name="android.permission.LOG_COMPAT_CHANGE" /> + <permission name="android.permission.READ_SYSTEM_GRAMMATICAL_GENDER"/> </privapp-permissions> <privapp-permissions package="com.android.providers.downloads"> @@ -205,6 +222,7 @@ applications that come with the platform <permission name="android.permission.UPDATE_APP_OPS_STATS"/> <permission name="android.permission.UPDATE_DEVICE_STATS"/> <permission name="android.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS"/> + <permission name="android.permission.READ_SYSTEM_GRAMMATICAL_GENDER"/> </privapp-permissions> <privapp-permissions package="com.android.providers.telephony"> @@ -214,6 +232,7 @@ applications that come with the platform <!-- Permissions required for reading and logging compat changes --> <permission name="android.permission.LOG_COMPAT_CHANGE" /> <permission name="android.permission.READ_COMPAT_CHANGE_CONFIG" /> + <permission name="android.permission.READ_SYSTEM_GRAMMATICAL_GENDER"/> </privapp-permissions> <privapp-permissions package="com.android.server.telecom"> @@ -229,11 +248,13 @@ applications that come with the platform <permission name="android.permission.MODIFY_PHONE_STATE"/> <permission name="android.permission.STOP_APP_SWITCHES"/> <permission name="android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME"/> + <permission name="android.permission.READ_SYSTEM_GRAMMATICAL_GENDER"/> </privapp-permissions> <privapp-permissions package="com.android.sharedstoragebackup"> <permission name="android.permission.WRITE_MEDIA_STORAGE"/> <permission name="android.permission.MANAGE_EXTERNAL_STORAGE"/> + <permission name="android.permission.READ_SYSTEM_GRAMMATICAL_GENDER"/> </privapp-permissions> <privapp-permissions package="com.android.shell"> @@ -400,6 +421,8 @@ applications that come with the platform <permission name="android.permission.REQUEST_COMPANION_PROFILE_NEARBY_DEVICE_STREAMING" /> <permission name="android.permission.REQUEST_COMPANION_PROFILE_COMPUTER" /> <permission name="android.permission.REQUEST_COMPANION_SELF_MANAGED" /> + <permission name="android.permission.REQUEST_OBSERVE_DEVICE_UUID_PRESENCE" /> + <!-- Permission required for testing registering pull atom callbacks. --> <permission name="android.permission.REGISTER_STATS_PULL_ATOM"/> <!-- Permission required for testing system audio effect APIs. --> @@ -547,16 +570,19 @@ applications that come with the platform <permission name="android.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS" /> <!-- Permission required for BinaryTransparencyService shell API and host test --> <permission name="android.permission.GET_BACKGROUND_INSTALLED_PACKAGES" /> + <permission name="android.permission.READ_SYSTEM_GRAMMATICAL_GENDER"/> </privapp-permissions> <privapp-permissions package="com.android.statementservice"> <permission name="android.permission.INTENT_FILTER_VERIFICATION_AGENT"/> <permission name="android.permission.DOMAIN_VERIFICATION_AGENT"/> <permission name="android.permission.INTERACT_ACROSS_USERS"/> + <permission name="android.permission.READ_SYSTEM_GRAMMATICAL_GENDER"/> </privapp-permissions> <privapp-permissions package="com.android.soundpicker"> <permission name="android.permission.INTERACT_ACROSS_USERS" /> + <permission name="android.permission.READ_SYSTEM_GRAMMATICAL_GENDER"/> </privapp-permissions> <privapp-permissions package="com.android.tv"> @@ -568,15 +594,18 @@ applications that come with the platform <permission name="android.permission.READ_CONTENT_RATING_SYSTEMS"/> <permission name="com.android.providers.tv.permission.ACCESS_ALL_EPG_DATA"/> <permission name="com.android.providers.tv.permission.ACCESS_WATCHED_PROGRAMS"/> + <permission name="android.permission.READ_SYSTEM_GRAMMATICAL_GENDER"/> </privapp-permissions> <privapp-permissions package="com.android.vpndialogs"> <permission name="android.permission.CONTROL_VPN"/> + <permission name="android.permission.READ_SYSTEM_GRAMMATICAL_GENDER"/> </privapp-permissions> <privapp-permissions package="com.android.wallpaper.livepicker"> <permission name="android.permission.SET_WALLPAPER_COMPONENT"/> <permission name="android.permission.BIND_WALLPAPER"/> + <permission name="android.permission.READ_SYSTEM_GRAMMATICAL_GENDER"/> </privapp-permissions> <privapp-permissions package="com.android.wallpaper"> @@ -584,26 +613,31 @@ applications that come with the platform <permission name="android.permission.BIND_WALLPAPER"/> <permission name="android.permission.CUSTOMIZE_SYSTEM_UI"/> <permission name="android.permission.SET_WALLPAPER_DIM_AMOUNT"/> + <permission name="android.permission.READ_SYSTEM_GRAMMATICAL_GENDER"/> </privapp-permissions> <privapp-permissions package="com.android.dynsystem"> <permission name="android.permission.REBOOT"/> <permission name="android.permission.MANAGE_DYNAMIC_SYSTEM"/> <permission name="android.permission.READ_OEM_UNLOCK_STATE"/> + <permission name="android.permission.READ_SYSTEM_GRAMMATICAL_GENDER"/> </privapp-permissions> <privapp-permissions package="com.android.settings"> <permission name="android.permission.INSTALL_DYNAMIC_SYSTEM"/> <permission name="android.permission.BIND_CELL_BROADCAST_SERVICE"/> <permission name="android.permission.READ_SAFETY_CENTER_STATUS" /> <permission name="android.permission.SEND_SAFETY_CENTER_UPDATE" /> + <permission name="android.permission.READ_SYSTEM_GRAMMATICAL_GENDER"/> </privapp-permissions> <privapp-permissions package="com.android.bips"> <permission name="android.permission.SUBSTITUTE_SHARE_TARGET_APP_NAME_AND_ICON"/> + <permission name="android.permission.READ_SYSTEM_GRAMMATICAL_GENDER"/> </privapp-permissions> <privapp-permissions package="com.android.calllogbackup"> <permission name="com.android.voicemail.permission.READ_VOICEMAIL"/> + <permission name="android.permission.READ_SYSTEM_GRAMMATICAL_GENDER"/> </privapp-permissions> <privapp-permissions package="com.android.devicediagnostics"> diff --git a/graphics/java/android/graphics/BaseRecordingCanvas.java b/graphics/java/android/graphics/BaseRecordingCanvas.java index d659ddd75f72..4e88b0efd3e5 100644 --- a/graphics/java/android/graphics/BaseRecordingCanvas.java +++ b/graphics/java/android/graphics/BaseRecordingCanvas.java @@ -607,7 +607,8 @@ public class BaseRecordingCanvas extends Canvas { } @Override - public final void drawMesh(@NonNull Mesh mesh, BlendMode blendMode, @NonNull Paint paint) { + public final void drawMesh(@NonNull Mesh mesh, @Nullable BlendMode blendMode, + @NonNull Paint paint) { if (blendMode == null) { blendMode = BlendMode.MODULATE; } diff --git a/graphics/java/android/graphics/text/LineBreaker.java b/graphics/java/android/graphics/text/LineBreaker.java index 0e3fb163ef75..97071260402c 100644 --- a/graphics/java/android/graphics/text/LineBreaker.java +++ b/graphics/java/android/graphics/text/LineBreaker.java @@ -17,6 +17,7 @@ package android.graphics.text; import static com.android.text.flags.Flags.FLAG_USE_BOUNDS_FOR_WIDTH; +import static com.android.text.flags.Flags.FLAG_INTER_CHARACTER_JUSTIFICATION; import android.annotation.FlaggedApi; import android.annotation.FloatRange; @@ -163,7 +164,8 @@ public class LineBreaker { /** @hide */ @IntDef(prefix = { "JUSTIFICATION_MODE_" }, value = { JUSTIFICATION_MODE_NONE, - JUSTIFICATION_MODE_INTER_WORD + JUSTIFICATION_MODE_INTER_WORD, + JUSTIFICATION_MODE_INTER_CHARACTER, }) @Retention(RetentionPolicy.SOURCE) public @interface JustificationMode {} @@ -179,6 +181,12 @@ public class LineBreaker { public static final int JUSTIFICATION_MODE_INTER_WORD = 1; /** + * Value for justification mode indicating the text is justified by stretching letter spacing. + */ + @FlaggedApi(FLAG_INTER_CHARACTER_JUSTIFICATION) + public static final int JUSTIFICATION_MODE_INTER_CHARACTER = 2; + + /** * Helper class for creating a {@link LineBreaker}. */ public static final class Builder { 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 83d555cbdecd..14a46778810c 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java @@ -17,6 +17,7 @@ package androidx.window.extensions.embedding; import static android.app.ActivityManager.START_SUCCESS; +import static android.app.ActivityOptions.KEY_LAUNCH_TASK_FRAGMENT_TOKEN; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.view.Display.DEFAULT_DISPLAY; @@ -110,6 +111,10 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen static final boolean ENABLE_SHELL_TRANSITIONS = SystemProperties.getBoolean("persist.wm.debug.shell_transit", true); + // TODO(b/295993745): remove after prebuilt library is updated. + private static final String KEY_ACTIVITY_STACK_TOKEN = + "androidx.window.extensions.embedding.ActivityStackToken"; + @VisibleForTesting @GuardedBy("mLock") final SplitPresenter mPresenter; @@ -2779,8 +2784,17 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen // TODO(b/232042367): Consolidate the activity create handling so that we can handle // cross-process the same as normal. + IBinder activityStackToken = options.getBinder(KEY_ACTIVITY_STACK_TOKEN); + if (activityStackToken != null) { + // Put activityStack token to #KEY_LAUNCH_TASK_FRAGMENT_TOKEN to launch the activity + // into the taskFragment associated with the token. + options.putBinder(KEY_LAUNCH_TASK_FRAGMENT_TOKEN, activityStackToken); + } + // Early return if the launching taskfragment is already been set. - if (options.getBinder(ActivityOptions.KEY_LAUNCH_TASK_FRAGMENT_TOKEN) != null) { + // TODO(b/295993745): Use KEY_LAUNCH_TASK_FRAGMENT_TOKEN after WM Jetpack migrates to + // bundle. This is still needed to support #setLaunchingActivityStack. + if (options.getBinder(KEY_LAUNCH_TASK_FRAGMENT_TOKEN) != null) { synchronized (mLock) { mCurrentIntent = intent; } @@ -2837,7 +2851,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen // Amend the request to let the WM know that the activity should be placed in // the dedicated container. // TODO(b/229680885): skip override launching TaskFragment token by split-rule - options.putBinder(ActivityOptions.KEY_LAUNCH_TASK_FRAGMENT_TOKEN, + options.putBinder(KEY_LAUNCH_TASK_FRAGMENT_TOKEN, launchedInTaskFragment.getTaskFragmentToken()); mCurrentIntent = intent; } else { @@ -2855,8 +2869,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen if (mCurrentIntent != null && result != START_SUCCESS) { // Clear the pending appeared intent if the activity was not started // successfully. - final IBinder token = bOptions.getBinder( - ActivityOptions.KEY_LAUNCH_TASK_FRAGMENT_TOKEN); + final IBinder token = bOptions.getBinder(KEY_LAUNCH_TASK_FRAGMENT_TOKEN); if (token != null) { final TaskFragmentContainer container = getContainer(token); if (container != null) { diff --git a/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/BubbleTaskViewTest.kt b/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/BubbleTaskViewTest.kt new file mode 100644 index 000000000000..4c76168cdeaa --- /dev/null +++ b/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/BubbleTaskViewTest.kt @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.wm.shell.bubbles + +import android.content.ComponentName +import android.content.Context +import androidx.test.core.app.ApplicationProvider +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.wm.shell.taskview.TaskView +import com.android.wm.shell.taskview.TaskViewTaskController + +import com.google.common.truth.Truth.assertThat +import com.google.common.util.concurrent.MoreExecutors.directExecutor +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.kotlin.mock + +@SmallTest +@RunWith(AndroidJUnit4::class) +class BubbleTaskViewTest { + + private lateinit var bubbleTaskView: BubbleTaskView + private val context = ApplicationProvider.getApplicationContext<Context>() + + @Before + fun setUp() { + val taskView = TaskView(context, mock<TaskViewTaskController>()) + bubbleTaskView = BubbleTaskView(taskView, directExecutor()) + } + + @Test + fun onTaskCreated_updatesState() { + val componentName = ComponentName(context, "TestClass") + bubbleTaskView.listener.onTaskCreated(123, componentName) + + assertThat(bubbleTaskView.taskId).isEqualTo(123) + assertThat(bubbleTaskView.componentName).isEqualTo(componentName) + assertThat(bubbleTaskView.isCreated).isTrue() + } + + @Test + fun onTaskCreated_callsDelegateListener() { + var actualTaskId = -1 + var actualComponentName: ComponentName? = null + val delegateListener = object : TaskView.Listener { + override fun onTaskCreated(taskId: Int, name: ComponentName) { + actualTaskId = taskId + actualComponentName = name + } + } + bubbleTaskView.delegateListener = delegateListener + + val componentName = ComponentName(context, "TestClass") + bubbleTaskView.listener.onTaskCreated(123, componentName) + + assertThat(actualTaskId).isEqualTo(123) + assertThat(actualComponentName).isEqualTo(componentName) + } +} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityBackAnimation.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityBackAnimation.java index 30d5edb59c85..160f922dd928 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityBackAnimation.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityBackAnimation.java @@ -199,6 +199,10 @@ public class CrossActivityBackAnimation extends ShellBackAnimation { } private void applyTransform(SurfaceControl leash, RectF targetRect, float targetAlpha) { + if (leash == null || !leash.isValid()) { + return; + } + final float scale = targetRect.width() / mStartTaskRect.width(); mTransformMatrix.reset(); mTransformMatrix.setScale(scale, scale); @@ -211,12 +215,16 @@ public class CrossActivityBackAnimation extends ShellBackAnimation { private void finishAnimation() { if (mEnteringTarget != null) { - mTransaction.setCornerRadius(mEnteringTarget.leash, 0); - mEnteringTarget.leash.release(); + if (mEnteringTarget.leash != null && mEnteringTarget.leash.isValid()) { + mTransaction.setCornerRadius(mEnteringTarget.leash, 0); + mEnteringTarget.leash.release(); + } mEnteringTarget = null; } if (mClosingTarget != null) { - mClosingTarget.leash.release(); + if (mClosingTarget.leash != null) { + mClosingTarget.leash.release(); + } mClosingTarget = null; } if (mBackground != null) { @@ -260,7 +268,9 @@ public class CrossActivityBackAnimation extends ShellBackAnimation { } private void onGestureCommitted() { - if (mEnteringTarget == null || mClosingTarget == null) { + if (mEnteringTarget == null || mClosingTarget == null || mClosingTarget.leash == null + || mEnteringTarget.leash == null || !mEnteringTarget.leash.isValid() + || !mClosingTarget.leash.isValid()) { finishAnimation(); return; } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossTaskBackAnimation.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossTaskBackAnimation.java index ac2a1c867462..adc78391f033 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossTaskBackAnimation.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossTaskBackAnimation.java @@ -208,7 +208,9 @@ public class CrossTaskBackAnimation extends ShellBackAnimation { float top = mapRange(progress, mClosingStartRect.top, targetTop); float width = mapRange(progress, mClosingStartRect.width(), targetWidth); float height = mapRange(progress, mClosingStartRect.height(), targetHeight); - mTransaction.setLayer(mClosingTarget.leash, 0); + if (mClosingTarget.leash != null && mClosingTarget.leash.isValid()) { + mTransaction.setLayer(mClosingTarget.leash, 0); + } mClosingCurrentRect.set(left, top, left + width, top + height); applyTransform(mClosingTarget.leash, mClosingCurrentRect, mCornerRadius); @@ -226,7 +228,7 @@ public class CrossTaskBackAnimation extends ShellBackAnimation { /** Transform the target window to match the target rect. */ private void applyTransform(SurfaceControl leash, RectF targetRect, float cornerRadius) { - if (leash == null) { + if (leash == null || !leash.isValid()) { return; } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java index 7a3210e0a46d..87c8f526c6fa 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java @@ -64,7 +64,7 @@ public class Bubble implements BubbleViewProvider { private static final String TAG = "Bubble"; /** A string suffix used in app bubbles' {@link #mKey}. */ - private static final String KEY_APP_BUBBLE = "key_app_bubble"; + public static final String KEY_APP_BUBBLE = "key_app_bubble"; /** Whether the bubble is an app bubble. */ private final boolean mIsAppBubble; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java index e23e15f95640..a5f7880cfd41 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java @@ -137,7 +137,7 @@ import java.util.function.IntConsumer; * The controller manages addition, removal, and visible state of bubbles on screen. */ public class BubbleController implements ConfigurationChangeListener, - RemoteCallable<BubbleController> { + RemoteCallable<BubbleController>, Bubbles.SysuiProxy.Provider { private static final String TAG = TAG_WITH_CLASS_NAME ? "BubbleController" : TAG_BUBBLES; @@ -706,6 +706,7 @@ public class BubbleController implements ConfigurationChangeListener, return mBubbleIconFactory; } + @Override public Bubbles.SysuiProxy getSysuiProxy() { return mSysuiProxy; } @@ -732,8 +733,7 @@ public class BubbleController implements ConfigurationChangeListener, if (mStackView == null) { mStackView = new BubbleStackView( mContext, this, mBubbleData, mSurfaceSynchronizer, - mFloatingContentCoordinator, - mMainExecutor); + mFloatingContentCoordinator, this, mMainExecutor); mStackView.onOrientationChanged(); if (mExpandListener != null) { mStackView.setExpandListener(mExpandListener); @@ -1249,7 +1249,7 @@ public class BubbleController implements ConfigurationChangeListener, } String appBubbleKey = Bubble.getAppBubbleKeyForApp(intent.getPackage(), user); - Log.v(TAG, "showOrHideAppBubble, with key: " + appBubbleKey); + Log.i(TAG, "showOrHideAppBubble, with key: " + appBubbleKey); PackageManager packageManager = getPackageManagerForUser(mContext, user.getIdentifier()); if (!isResizableActivity(intent, packageManager, appBubbleKey)) return; @@ -1259,22 +1259,22 @@ public class BubbleController implements ConfigurationChangeListener, if (isStackExpanded()) { if (selectedBubble != null && appBubbleKey.equals(selectedBubble.getKey())) { // App bubble is expanded, lets collapse - Log.v(TAG, " showOrHideAppBubble, selected bubble is app bubble, collapsing"); + Log.i(TAG, " showOrHideAppBubble, selected bubble is app bubble, collapsing"); collapseStack(); } else { // App bubble is not selected, select it - Log.v(TAG, " showOrHideAppBubble, expanded, selecting existing app bubble"); + Log.i(TAG, " showOrHideAppBubble, expanded, selecting existing app bubble"); mBubbleData.setSelectedBubble(existingAppBubble); } } else { // App bubble is not selected, select it & expand - Log.v(TAG, " showOrHideAppBubble, expand and select existing app bubble"); + Log.i(TAG, " showOrHideAppBubble, expand and select existing app bubble"); mBubbleData.setSelectedBubble(existingAppBubble); mBubbleData.setExpanded(true); } } else { // App bubble does not exist, lets add and expand it - Log.v(TAG, " showOrHideAppBubble, creating and expanding app bubble"); + Log.i(TAG, " showOrHideAppBubble, creating and expanding app bubble"); Bubble b = Bubble.createAppBubble(intent, user, icon, mMainExecutor); b.setShouldAutoExpand(true); inflateAndAdd(b, /* suppressFlyout= */ true, /* showInShade= */ false); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java index bbb4b74c2a17..6e0c804f0676 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java @@ -17,6 +17,7 @@ package com.android.wm.shell.bubbles; import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE; import static com.android.internal.annotations.VisibleForTesting.Visibility.PRIVATE; +import static com.android.wm.shell.bubbles.Bubble.KEY_APP_BUBBLE; import static com.android.wm.shell.bubbles.BubbleDebugConfig.DEBUG_BUBBLE_DATA; import static com.android.wm.shell.bubbles.BubbleDebugConfig.TAG_BUBBLES; import static com.android.wm.shell.bubbles.BubbleDebugConfig.TAG_WITH_CLASS_NAME; @@ -649,8 +650,8 @@ public class BubbleData { } private void doRemove(String key, @DismissReason int reason) { - if (DEBUG_BUBBLE_DATA) { - Log.d(TAG, "doRemove: " + key); + if (DEBUG_BUBBLE_DATA || (key != null && key.contains(KEY_APP_BUBBLE))) { + Log.d(TAG, "doRemove: " + key + " reason: " + reason); } // If it was pending remove it if (mPendingBubbles.containsKey(key)) { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java index f3fe895bf9b4..9f7d0ac9bafe 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java @@ -74,7 +74,6 @@ import com.android.wm.shell.R; import com.android.wm.shell.common.AlphaOptimizedButton; import com.android.wm.shell.common.TriangleShape; import com.android.wm.shell.taskview.TaskView; -import com.android.wm.shell.taskview.TaskViewTaskController; import java.io.PrintWriter; @@ -146,7 +145,6 @@ public class BubbleExpandedView extends LinearLayout { private AlphaOptimizedButton mManageButton; private TaskView mTaskView; - private TaskViewTaskController mTaskViewTaskController; private BubbleOverflowContainerView mOverflowView; private int mTaskId = INVALID_TASK_ID; @@ -434,7 +432,8 @@ public class BubbleExpandedView extends LinearLayout { * Initialize {@link BubbleController} and {@link BubbleStackView} here, this method must need * to be called after view inflate. */ - void initialize(BubbleController controller, BubbleStackView stackView, boolean isOverflow) { + void initialize(BubbleController controller, BubbleStackView stackView, boolean isOverflow, + @Nullable BubbleTaskView bubbleTaskView) { mController = controller; mStackView = stackView; mIsOverflow = isOverflow; @@ -451,18 +450,22 @@ public class BubbleExpandedView extends LinearLayout { bringChildToFront(mOverflowView); mManageButton.setVisibility(GONE); } else { - mTaskViewTaskController = new TaskViewTaskController(mContext, - mController.getTaskOrganizer(), - mController.getTaskViewTransitions(), mController.getSyncTransactionQueue()); - mTaskView = new TaskView(mContext, mTaskViewTaskController); - mTaskView.setListener(mController.getMainExecutor(), mTaskViewListener); + mTaskView = bubbleTaskView.getTaskView(); + bubbleTaskView.setDelegateListener(mTaskViewListener); // set a fixed width so it is not recalculated as part of a rotation. the width will be // updated manually after the rotation. FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(getContentWidth(), MATCH_PARENT); + if (mTaskView.getParent() != null) { + ((ViewGroup) mTaskView.getParent()).removeView(mTaskView); + } mExpandedViewContainer.addView(mTaskView, lp); bringChildToFront(mTaskView); + if (bubbleTaskView.isCreated()) { + mTaskViewListener.onTaskCreated( + bubbleTaskView.getTaskId(), bubbleTaskView.getComponentName()); + } } } @@ -876,7 +879,7 @@ public class BubbleExpandedView extends LinearLayout { return; } boolean isNew = mBubble == null || didBackingContentChange(bubble); - if (isNew || bubble != null && bubble.getKey().equals(mBubble.getKey())) { + if (isNew || bubble.getKey().equals(mBubble.getKey())) { mBubble = bubble; mManageButton.setContentDescription(getResources().getString( R.string.bubbles_settings_button_description, bubble.getAppName())); @@ -1107,7 +1110,8 @@ public class BubbleExpandedView extends LinearLayout { * has been removed. * * If this view should be reused after this method is called, then - * {@link #initialize(BubbleController, BubbleStackView, boolean)} must be invoked first. + * {@link #initialize(BubbleController, BubbleStackView, boolean, BubbleTaskView)} + * must be invoked first. */ public void cleanUpExpandedState() { if (DEBUG_BUBBLE_EXPANDED_VIEW) { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflow.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflow.kt index 22e836aacfc5..e5d9acedc903 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflow.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleOverflow.kt @@ -29,6 +29,7 @@ import android.util.PathParser import android.view.LayoutInflater import android.view.View.VISIBLE import android.widget.FrameLayout +import androidx.core.content.ContextCompat import com.android.launcher3.icons.BubbleIconFactory import com.android.wm.shell.R import com.android.wm.shell.bubbles.bar.BubbleBarExpandedView @@ -57,10 +58,16 @@ class BubbleOverflow(private val context: Context, private val positioner: Bubbl /** Call before use and again if cleanUpExpandedState was called. */ fun initialize(controller: BubbleController, forBubbleBar: Boolean) { if (forBubbleBar) { - createBubbleBarExpandedView().initialize(controller, true /* isOverflow */) + createBubbleBarExpandedView() + .initialize(controller, /* isOverflow= */ true, /* bubbleTaskView= */ null) } else { createExpandedView() - .initialize(controller, controller.stackView, true /* isOverflow */) + .initialize( + controller, + controller.stackView, + /* isOverflow= */ true, + /* bubbleTaskView= */ null + ) } } @@ -113,7 +120,10 @@ class BubbleOverflow(private val context: Context, private val positioner: Bubbl context, res.getDimensionPixelSize(R.dimen.bubble_size), res.getDimensionPixelSize(R.dimen.bubble_badge_size), - res.getColor(com.android.launcher3.icons.R.color.important_conversation), + ContextCompat.getColor( + context, + com.android.launcher3.icons.R.color.important_conversation + ), res.getDimensionPixelSize(com.android.internal.R.dimen.importance_ring_stroke_width) ) 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 c25d41275f2b..a619401301aa 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 @@ -206,6 +206,7 @@ public class BubbleStackView extends FrameLayout }; private final BubbleController mBubbleController; private final BubbleData mBubbleData; + private final Bubbles.SysuiProxy.Provider mSysuiProxyProvider; private StackViewState mStackViewState = new StackViewState(); private final ValueAnimator mDismissBubbleAnimator; @@ -875,12 +876,14 @@ public class BubbleStackView extends FrameLayout public BubbleStackView(Context context, BubbleController bubbleController, BubbleData data, @Nullable SurfaceSynchronizer synchronizer, FloatingContentCoordinator floatingContentCoordinator, + Bubbles.SysuiProxy.Provider sysuiProxyProvider, ShellExecutor mainExecutor) { super(context); mMainExecutor = mainExecutor; mBubbleController = bubbleController; mBubbleData = data; + mSysuiProxyProvider = sysuiProxyProvider; Resources res = getResources(); mBubbleSize = res.getDimensionPixelSize(R.dimen.bubble_size); @@ -2090,7 +2093,7 @@ public class BubbleStackView extends FrameLayout hideCurrentInputMethod(); - mBubbleController.getSysuiProxy().onStackExpandChanged(shouldExpand); + mSysuiProxyProvider.getSysuiProxy().onStackExpandChanged(shouldExpand); if (wasExpanded) { stopMonitoringSwipeUpGesture(); @@ -3034,7 +3037,7 @@ public class BubbleStackView extends FrameLayout if (mExpandedBubble == null || mExpandedBubble.getExpandedView() == null) { mManageMenu.setVisibility(View.INVISIBLE); mManageMenuScrim.setVisibility(INVISIBLE); - mBubbleController.getSysuiProxy().onManageMenuExpandChanged(false /* show */); + mSysuiProxyProvider.getSysuiProxy().onManageMenuExpandChanged(false /* show */); return; } if (show) { @@ -3048,7 +3051,7 @@ public class BubbleStackView extends FrameLayout } }; - mBubbleController.getSysuiProxy().onManageMenuExpandChanged(show); + mSysuiProxyProvider.getSysuiProxy().onManageMenuExpandChanged(show); mManageMenuScrim.animate() .setInterpolator(show ? ALPHA_IN : ALPHA_OUT) .alpha(show ? BUBBLE_EXPANDED_SCRIM_ALPHA : 0f) diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTaskView.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTaskView.kt new file mode 100644 index 000000000000..2fcd133c7b20 --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTaskView.kt @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.wm.shell.bubbles + +import android.app.ActivityTaskManager.INVALID_TASK_ID +import android.content.ComponentName +import androidx.annotation.VisibleForTesting +import com.android.wm.shell.taskview.TaskView +import java.util.concurrent.Executor + +/** + * A wrapper class around [TaskView] for bubble expanded views. + * + * [delegateListener] allows callers to change listeners after a task has been created. + */ +class BubbleTaskView(val taskView: TaskView, executor: Executor) { + + /** Whether the task is already created. */ + var isCreated = false + private set + + /** The task id. */ + var taskId = INVALID_TASK_ID + private set + + /** The component name of the application running in the task. */ + var componentName: ComponentName? = null + private set + + /** [TaskView.Listener] for users of this class. */ + var delegateListener: TaskView.Listener? = null + + /** A [TaskView.Listener] that delegates to [delegateListener]. */ + @get:VisibleForTesting + val listener = object : TaskView.Listener { + override fun onInitialized() { + delegateListener?.onInitialized() + } + + override fun onReleased() { + delegateListener?.onReleased() + } + + override fun onTaskCreated(taskId: Int, name: ComponentName) { + delegateListener?.onTaskCreated(taskId, name) + this@BubbleTaskView.taskId = taskId + isCreated = true + componentName = name + } + + override fun onTaskVisibilityChanged(taskId: Int, visible: Boolean) { + delegateListener?.onTaskVisibilityChanged(taskId, visible) + } + + override fun onTaskRemovalStarted(taskId: Int) { + delegateListener?.onTaskRemovalStarted(taskId) + } + + override fun onBackPressedOnTaskRoot(taskId: Int) { + delegateListener?.onBackPressedOnTaskRoot(taskId) + } + } + + init { + taskView.setListener(executor, listener) + } +} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTaskViewHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTaskViewHelper.java index f6c382fb5b3d..5855a81333d4 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTaskViewHelper.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleTaskViewHelper.java @@ -35,10 +35,7 @@ import android.view.View; import androidx.annotation.Nullable; -import com.android.wm.shell.common.ShellExecutor; -import com.android.wm.shell.common.annotations.ShellMainThread; import com.android.wm.shell.taskview.TaskView; -import com.android.wm.shell.taskview.TaskViewTaskController; /** * Handles creating and updating the {@link TaskView} associated with a {@link Bubble}. @@ -65,7 +62,6 @@ public class BubbleTaskViewHelper { private final Context mContext; private final BubbleController mController; - private final @ShellMainThread ShellExecutor mMainExecutor; private final BubbleTaskViewHelper.Listener mListener; private final View mParentView; @@ -73,7 +69,6 @@ public class BubbleTaskViewHelper { private Bubble mBubble; @Nullable private PendingIntent mPendingIntent; - private TaskViewTaskController mTaskViewTaskController; @Nullable private TaskView mTaskView; private int mTaskId = INVALID_TASK_ID; @@ -204,17 +199,18 @@ public class BubbleTaskViewHelper { public BubbleTaskViewHelper(Context context, BubbleController controller, BubbleTaskViewHelper.Listener listener, + BubbleTaskView bubbleTaskView, View parent) { mContext = context; mController = controller; - mMainExecutor = mController.getMainExecutor(); mListener = listener; mParentView = parent; - mTaskViewTaskController = new TaskViewTaskController(mContext, - mController.getTaskOrganizer(), - mController.getTaskViewTransitions(), mController.getSyncTransactionQueue()); - mTaskView = new TaskView(mContext, mTaskViewTaskController); - mTaskView.setListener(mMainExecutor, mTaskViewListener); + mTaskView = bubbleTaskView.getTaskView(); + bubbleTaskView.setDelegateListener(mTaskViewListener); + if (bubbleTaskView.isCreated()) { + mTaskId = bubbleTaskView.getTaskId(); + mListener.onTaskCreated(); + } } /** diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java index bb30c5eeebcf..c3d899e7dac7 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java @@ -46,6 +46,8 @@ import com.android.launcher3.icons.BubbleIconFactory; import com.android.wm.shell.R; import com.android.wm.shell.bubbles.bar.BubbleBarExpandedView; import com.android.wm.shell.bubbles.bar.BubbleBarLayerView; +import com.android.wm.shell.taskview.TaskView; +import com.android.wm.shell.taskview.TaskViewTaskController; import java.lang.ref.WeakReference; import java.util.Objects; @@ -173,10 +175,12 @@ public class BubbleViewInfoTask extends AsyncTask<Void, Void, BubbleViewInfoTask BubbleViewInfo info = new BubbleViewInfo(); if (!skipInflation && !b.isInflated()) { + BubbleTaskView bubbleTaskView = createBubbleTaskView(c, controller); LayoutInflater inflater = LayoutInflater.from(c); info.bubbleBarExpandedView = (BubbleBarExpandedView) inflater.inflate( R.layout.bubble_bar_expanded_view, layerView, false /* attachToRoot */); - info.bubbleBarExpandedView.initialize(controller, false /* isOverflow */); + info.bubbleBarExpandedView.initialize( + controller, false /* isOverflow */, bubbleTaskView); } if (!populateCommonInfo(info, c, b, iconFactory)) { @@ -201,9 +205,11 @@ public class BubbleViewInfoTask extends AsyncTask<Void, Void, BubbleViewInfoTask R.layout.bubble_view, stackView, false /* attachToRoot */); info.imageView.initialize(controller.getPositioner()); + BubbleTaskView bubbleTaskView = createBubbleTaskView(c, controller); info.expandedView = (BubbleExpandedView) inflater.inflate( R.layout.bubble_expanded_view, stackView, false /* attachToRoot */); - info.expandedView.initialize(controller, stackView, false /* isOverflow */); + info.expandedView.initialize( + controller, stackView, false /* isOverflow */, bubbleTaskView); } if (!populateCommonInfo(info, c, b, iconFactory)) { @@ -219,6 +225,15 @@ public class BubbleViewInfoTask extends AsyncTask<Void, Void, BubbleViewInfoTask } return info; } + + private static BubbleTaskView createBubbleTaskView( + Context context, BubbleController controller) { + TaskViewTaskController taskViewTaskController = new TaskViewTaskController(context, + controller.getTaskOrganizer(), + controller.getTaskViewTransitions(), controller.getSyncTransactionQueue()); + TaskView taskView = new TaskView(context, taskViewTaskController); + return new BubbleTaskView(taskView, controller.getMainExecutor()); + } } /** diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java index 759246eb285d..28af0ca6ac6c 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java @@ -321,6 +321,13 @@ public interface Bubbles { /** Callback to tell SysUi components execute some methods. */ interface SysuiProxy { + + /** Provider interface for {@link SysuiProxy}. */ + interface Provider { + /** Returns {@link SysuiProxy}. */ + SysuiProxy getSysuiProxy(); + } + void isNotificationPanelExpand(Consumer<Boolean> callback); void getPendingOrActiveEntry(String key, Consumer<BubbleEntry> callback); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java index 66c0c9640477..3cf23ac114ee 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java @@ -16,6 +16,8 @@ package com.android.wm.shell.bubbles.bar; +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; + import android.annotation.Nullable; import android.app.ActivityManager; import android.content.Context; @@ -27,6 +29,7 @@ import android.graphics.Rect; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; +import android.view.ViewGroup; import android.view.ViewOutlineProvider; import android.widget.FrameLayout; @@ -35,6 +38,7 @@ import com.android.wm.shell.R; import com.android.wm.shell.bubbles.Bubble; import com.android.wm.shell.bubbles.BubbleController; import com.android.wm.shell.bubbles.BubbleOverflowContainerView; +import com.android.wm.shell.bubbles.BubbleTaskView; import com.android.wm.shell.bubbles.BubbleTaskViewHelper; import com.android.wm.shell.bubbles.Bubbles; import com.android.wm.shell.taskview.TaskView; @@ -130,7 +134,8 @@ public class BubbleBarExpandedView extends FrameLayout implements BubbleTaskView } /** Set the BubbleController on the view, must be called before doing anything else. */ - public void initialize(BubbleController controller, boolean isOverflow) { + public void initialize(BubbleController controller, boolean isOverflow, + @Nullable BubbleTaskView bubbleTaskView) { mController = controller; mIsOverflow = isOverflow; @@ -140,14 +145,19 @@ public class BubbleBarExpandedView extends FrameLayout implements BubbleTaskView mOverflowView.setBubbleController(mController); addView(mOverflowView); } else { - + mTaskView = bubbleTaskView.getTaskView(); mBubbleTaskViewHelper = new BubbleTaskViewHelper(mContext, mController, - /* listener= */ this, + /* listener= */ this, bubbleTaskView, /* viewParent= */ this); - mTaskView = mBubbleTaskViewHelper.getTaskView(); - addView(mTaskView); + if (mTaskView.getParent() != null) { + ((ViewGroup) mTaskView.getParent()).removeView(mTaskView); + } + FrameLayout.LayoutParams lp = + new FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT); + addView(mTaskView, lp); mTaskView.setEnableSurfaceClipping(true); mTaskView.setCornerRadius(mCornerRadius); + mTaskView.setVisibility(VISIBLE); // Handle view needs to draw on top of task view. bringChildToFront(mHandleView); 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 a9a3f788cb7e..07b8f11458be 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 @@ -599,9 +599,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, if (Transitions.ENABLE_SHELL_TRANSITIONS) { if (requestEnterSplit && mSplitScreenOptional.isPresent()) { wct.setWindowingMode(mToken, WINDOWING_MODE_UNDEFINED); - mSplitScreenOptional.get().prepareEnterSplitScreen(wct, mTaskInfo, - isPipToTopLeft() - ? SPLIT_POSITION_TOP_OR_LEFT : SPLIT_POSITION_BOTTOM_OR_RIGHT); + mSplitScreenOptional.get().onPipExpandToSplit(wct, mTaskInfo); mPipTransitionController.startExitTransition( TRANSIT_EXIT_PIP_TO_SPLIT, wct, destinationBounds); return; 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 880d95286de6..2ec52bb028c6 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 @@ -452,6 +452,17 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, } /** + * Performs previous child eviction and such to prepare for the pip task expending into one of + * the split stages + * + * @param taskInfo TaskInfo of the pip task + */ + public void onPipExpandToSplit(WindowContainerTransaction wct, + ActivityManager.RunningTaskInfo taskInfo) { + mStageCoordinator.onPipExpandToSplit(wct, taskInfo); + } + + /** * Doing necessary window transaction for other transition handler need to exit split in * transition. */ 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 0781a9e440f3..af05aa2c5ec6 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 @@ -2982,6 +2982,25 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, } + /** + * Performs previous child eviction and such to prepare for the pip task expending into one of + * the split stages + * + * @param taskInfo TaskInfo of the pip task + */ + public void onPipExpandToSplit(WindowContainerTransaction wct, + ActivityManager.RunningTaskInfo taskInfo) { + prepareEnterSplitScreen(wct, taskInfo, getActivateSplitPosition(taskInfo), + false /*resizeAnim*/); + + if (!isSplitScreenVisible() || mSplitRequest == null) { + return; + } + + boolean replacingMainStage = getMainStagePosition() == mSplitRequest.mActivatePosition; + (replacingMainStage ? mMainStage : mSideStage).evictOtherChildren(wct, taskInfo.taskId); + } + boolean isLaunchToSplit(TaskInfo taskInfo) { return getActivateSplitPosition(taskInfo) != SPLIT_POSITION_UNDEFINED; } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedTransition.java index 9ce46d69815b..e9cd73b0df5e 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedTransition.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedTransition.java @@ -95,8 +95,8 @@ class DefaultMixedTransition extends DefaultMixedHandler.MixedTransition { @NonNull SurfaceControl.Transaction startTransaction, @NonNull SurfaceControl.Transaction finishTransaction, @NonNull Transitions.TransitionFinishCallback finishCallback) { - ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Animating a mixed transition for " - + "entering PIP from an Activity Embedding window"); + ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Mixed transition for entering PIP from" + + " an Activity Embedding window #%d", info.getDebugId()); // Split into two transitions (wct) TransitionInfo.Change pipChange = null; final TransitionInfo everythingElse = subCopy(info, TRANSIT_TO_BACK, true /* changes */); @@ -146,6 +146,8 @@ class DefaultMixedTransition extends DefaultMixedHandler.MixedTransition { @NonNull SurfaceControl.Transaction startTransaction, @NonNull SurfaceControl.Transaction finishTransaction, @NonNull Transitions.TransitionFinishCallback finishCallback) { + ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Mixed transition for opening an intent" + + " with a remote transition and PIP #%d", info.getDebugId()); boolean handledToPip = tryAnimateOpenIntentWithRemoteAndPip( info, startTransaction, finishTransaction, finishCallback); // Consume the transition on remote handler if the leftover handler already handle this @@ -192,8 +194,9 @@ class DefaultMixedTransition extends DefaultMixedHandler.MixedTransition { } return false; } - ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Splitting PIP into a separate" - + " animation because remote-animation likely doesn't support it"); + ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Splitting PIP into a separate" + + " animation because remote-animation likely doesn't support it #%d", + info.getDebugId()); // Split the transition into 2 parts: the pip part and the rest. mInFlightSubAnimations = 2; // make a new startTransaction because pip's startEnterAnimation "consumes" it so @@ -218,6 +221,9 @@ class DefaultMixedTransition extends DefaultMixedHandler.MixedTransition { @NonNull SurfaceControl.Transaction startTransaction, @NonNull SurfaceControl.Transaction finishTransaction, @NonNull Transitions.TransitionFinishCallback finishCallback) { + ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Mixed transition for unfolding #%d", + info.getDebugId()); + final Transitions.TransitionFinishCallback finishCB = (wct) -> { mInFlightSubAnimations--; if (mInFlightSubAnimations > 0) return; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RecentsMixedTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RecentsMixedTransition.java index 643e0266d7df..4ea71490798c 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RecentsMixedTransition.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RecentsMixedTransition.java @@ -30,9 +30,11 @@ import android.view.SurfaceControl; import android.window.TransitionInfo; import android.window.WindowContainerTransaction; +import com.android.internal.protolog.common.ProtoLog; import com.android.wm.shell.desktopmode.DesktopTasksController; import com.android.wm.shell.keyguard.KeyguardTransitionHandler; import com.android.wm.shell.pip.PipTransitionController; +import com.android.wm.shell.protolog.ShellProtoLogGroup; import com.android.wm.shell.recents.RecentsTransitionHandler; import com.android.wm.shell.splitscreen.StageCoordinator; @@ -77,6 +79,9 @@ class RecentsMixedTransition extends DefaultMixedHandler.MixedTransition { @NonNull SurfaceControl.Transaction startTransaction, @NonNull SurfaceControl.Transaction finishTransaction, @NonNull Transitions.TransitionFinishCallback finishCallback) { + ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Transition for Recents during" + + " Desktop #%d", info.getDebugId()); + if (mInfo == null) { mInfo = info; mFinishT = finishTransaction; @@ -109,6 +114,9 @@ class RecentsMixedTransition extends DefaultMixedHandler.MixedTransition { @NonNull SurfaceControl.Transaction startTransaction, @NonNull SurfaceControl.Transaction finishTransaction, @NonNull Transitions.TransitionFinishCallback finishCallback) { + ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Mixed transition for Recents during" + + " Keyguard #%d", info.getDebugId()); + if (mInfo == null) { mInfo = info; mFinishT = finishTransaction; @@ -122,6 +130,9 @@ class RecentsMixedTransition extends DefaultMixedHandler.MixedTransition { @NonNull SurfaceControl.Transaction startTransaction, @NonNull SurfaceControl.Transaction finishTransaction, @NonNull Transitions.TransitionFinishCallback finishCallback) { + ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Mixed transition for Recents during" + + " split screen #%d", info.getDebugId()); + for (int i = info.getChanges().size() - 1; i >= 0; --i) { final TransitionInfo.Change change = info.getChanges().get(i); // Pip auto-entering info might be appended to recent transition like pressing diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleViewInfoTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleViewInfoTest.kt index f58332198696..4878df806f82 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleViewInfoTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleViewInfoTest.kt @@ -125,7 +125,7 @@ class BubbleViewInfoTest : ShellTestCase() { mock<BubbleProperties>()) bubbleStackView = BubbleStackView(context, bubbleController, bubbleData, - surfaceSynchronizer, FloatingContentCoordinator(), mainExecutor) + surfaceSynchronizer, FloatingContentCoordinator(), bubbleController, mainExecutor) bubbleBarLayerView = BubbleBarLayerView(context, bubbleController) } diff --git a/libs/hwui/AutoBackendTextureRelease.cpp b/libs/hwui/AutoBackendTextureRelease.cpp index 4d020c567972..5f5ffe97e953 100644 --- a/libs/hwui/AutoBackendTextureRelease.cpp +++ b/libs/hwui/AutoBackendTextureRelease.cpp @@ -21,6 +21,7 @@ #include <include/gpu/GrDirectContext.h> #include <include/gpu/GrBackendSurface.h> #include <include/gpu/MutableTextureState.h> +#include <include/gpu/vk/VulkanMutableTextureState.h> #include "renderthread/RenderThread.h" #include "utils/Color.h" #include "utils/PaintUtils.h" @@ -142,8 +143,9 @@ void AutoBackendTextureRelease::releaseQueueOwnership(GrDirectContext* context) LOG_ALWAYS_FATAL_IF(Properties::getRenderPipelineType() != RenderPipelineType::SkiaVulkan); if (mBackendTexture.isValid()) { // Passing in VK_IMAGE_LAYOUT_UNDEFINED means we keep the old layout. - skgpu::MutableTextureState newState(VK_IMAGE_LAYOUT_UNDEFINED, - VK_QUEUE_FAMILY_FOREIGN_EXT); + skgpu::MutableTextureState newState = skgpu::MutableTextureStates::MakeVulkan( + VK_IMAGE_LAYOUT_UNDEFINED, + VK_QUEUE_FAMILY_FOREIGN_EXT); // The unref for this ref happens in the releaseProc passed into setBackendTextureState. The // releaseProc callback will be made when the work to set the new state has finished on the diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp index 0b42c88aa448..f526a280b113 100644 --- a/libs/hwui/RenderNode.cpp +++ b/libs/hwui/RenderNode.cpp @@ -230,7 +230,7 @@ void RenderNode::pushLayerUpdate(TreeInfo& info) { * stencil buffer may be needed. Views that use a functor to draw will be forced onto a layer. */ void RenderNode::prepareTreeImpl(TreeObserver& observer, TreeInfo& info, bool functorsNeedLayer) { - if (mDamageGenerationId == info.damageGenerationId) { + if (mDamageGenerationId == info.damageGenerationId && mDamageGenerationId != 0) { // We hit the same node a second time in the same tree. We don't know the minimal // damage rect anymore, so just push the biggest we can onto our parent's transform // We push directly onto parent in case we are clipped to bounds but have moved position. diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h index 1f3834be5bef..c9045427bd42 100644 --- a/libs/hwui/RenderNode.h +++ b/libs/hwui/RenderNode.h @@ -262,7 +262,7 @@ private: DisplayList mDisplayList; DisplayList mStagingDisplayList; - int64_t mDamageGenerationId; + int64_t mDamageGenerationId = 0; friend class AnimatorManager; AnimatorManager mAnimatorManager; diff --git a/libs/hwui/jni/PathMeasure.cpp b/libs/hwui/jni/PathMeasure.cpp index acf893e9544c..79acb6cc35e5 100644 --- a/libs/hwui/jni/PathMeasure.cpp +++ b/libs/hwui/jni/PathMeasure.cpp @@ -17,7 +17,11 @@ #include "GraphicsJNI.h" +#include "SkMatrix.h" +#include "SkPath.h" #include "SkPathMeasure.h" +#include "SkPoint.h" +#include "SkScalar.h" /* We declare an explicit pair, so that we don't have to rely on the java client to be sure not to edit the path while we have an active measure diff --git a/libs/input/PointerController.cpp b/libs/input/PointerController.cpp index bba9c9764eee..f84107e8792c 100644 --- a/libs/input/PointerController.cpp +++ b/libs/input/PointerController.cpp @@ -111,7 +111,11 @@ PointerController::PointerController(const sp<PointerControllerPolicyInterface>& : PointerController( policy, looper, spriteController, enabled, [](const sp<android::gui::WindowInfosListener>& listener) { - SurfaceComposerClient::getDefault()->addWindowInfosListener(listener); + auto initialInfo = std::make_pair(std::vector<android::gui::WindowInfo>{}, + std::vector<android::gui::DisplayInfo>{}); + SurfaceComposerClient::getDefault()->addWindowInfosListener(listener, + &initialInfo); + return initialInfo.second; }, [](const sp<android::gui::WindowInfosListener>& listener) { SurfaceComposerClient::getDefault()->removeWindowInfosListener(listener); @@ -119,8 +123,9 @@ PointerController::PointerController(const sp<PointerControllerPolicyInterface>& PointerController::PointerController(const sp<PointerControllerPolicyInterface>& policy, const sp<Looper>& looper, SpriteController& spriteController, - bool enabled, WindowListenerConsumer registerListener, - WindowListenerConsumer unregisterListener) + bool enabled, + const WindowListenerRegisterConsumer& registerListener, + WindowListenerUnregisterConsumer unregisterListener) : mEnabled(enabled), mContext(policy, looper, spriteController, *this), mCursorController(mContext), @@ -128,7 +133,8 @@ PointerController::PointerController(const sp<PointerControllerPolicyInterface>& mUnregisterWindowInfosListener(std::move(unregisterListener)) { std::scoped_lock lock(getLock()); mLocked.presentation = Presentation::SPOT; - registerListener(mDisplayInfoListener); + const auto& initialDisplayInfos = registerListener(mDisplayInfoListener); + onDisplayInfosChangedLocked(initialDisplayInfos); } PointerController::~PointerController() { diff --git a/libs/input/PointerController.h b/libs/input/PointerController.h index a8b963367f4c..6ee5707622ca 100644 --- a/libs/input/PointerController.h +++ b/libs/input/PointerController.h @@ -79,14 +79,16 @@ public: std::string dump() override; protected: - using WindowListenerConsumer = + using WindowListenerRegisterConsumer = std::function<std::vector<gui::DisplayInfo>( + const sp<android::gui::WindowInfosListener>&)>; + using WindowListenerUnregisterConsumer = std::function<void(const sp<android::gui::WindowInfosListener>&)>; // Constructor used to test WindowInfosListener registration. PointerController(const sp<PointerControllerPolicyInterface>& policy, const sp<Looper>& looper, SpriteController& spriteController, bool enabled, - WindowListenerConsumer registerListener, - WindowListenerConsumer unregisterListener); + const WindowListenerRegisterConsumer& registerListener, + WindowListenerUnregisterConsumer unregisterListener); PointerController(const sp<PointerControllerPolicyInterface>& policy, const sp<Looper>& looper, SpriteController& spriteController, bool enabled); @@ -129,7 +131,7 @@ private: }; sp<DisplayInfoListener> mDisplayInfoListener; - const WindowListenerConsumer mUnregisterWindowInfosListener; + const WindowListenerUnregisterConsumer mUnregisterWindowInfosListener; const ui::Transform& getTransformForDisplayLocked(int displayId) const REQUIRES(getLock()); diff --git a/libs/input/TouchSpotController.cpp b/libs/input/TouchSpotController.cpp index b8de919fbd8c..99952aa14904 100644 --- a/libs/input/TouchSpotController.cpp +++ b/libs/input/TouchSpotController.cpp @@ -93,7 +93,7 @@ void TouchSpotController::setSpots(const PointerCoords* spotCoords, const uint32 const PointerCoords& c = spotCoords[spotIdToIndex[id]]; ALOGD(" spot %d: position=(%0.3f, %0.3f), pressure=%0.3f, displayId=%" PRId32 ".", id, c.getAxisValue(AMOTION_EVENT_AXIS_X), c.getAxisValue(AMOTION_EVENT_AXIS_Y), - c.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE), displayId); + c.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE), mDisplayId); } #endif diff --git a/libs/input/tests/PointerController_test.cpp b/libs/input/tests/PointerController_test.cpp index adfa91e96ebb..a1bb5b3f1cc4 100644 --- a/libs/input/tests/PointerController_test.cpp +++ b/libs/input/tests/PointerController_test.cpp @@ -160,9 +160,11 @@ public: : PointerController( policy, looper, spriteController, /*enabled=*/true, - [®isteredListener](const sp<android::gui::WindowInfosListener>& listener) { + [®isteredListener](const sp<android::gui::WindowInfosListener>& listener) + -> std::vector<gui::DisplayInfo> { // Register listener registeredListener = listener; + return {}; }, [®isteredListener](const sp<android::gui::WindowInfosListener>& listener) { // Unregister listener diff --git a/location/java/android/location/flags/gnss.aconfig b/location/java/android/location/flags/gnss.aconfig index 5f1279ecceea..8c7c8716b2dc 100644 --- a/location/java/android/location/flags/gnss.aconfig +++ b/location/java/android/location/flags/gnss.aconfig @@ -36,15 +36,15 @@ flag { } flag { - name: "gnss_configuration_from_resource" + name: "replace_future_elapsed_realtime_jni" namespace: "location" - description: "Flag for GNSS configuration from resource" - bug: "317734846" + description: "Flag for replacing future elapsedRealtime in JNI" + bug: "314328533" } flag { - name: "replace_future_elapsed_realtime_jni" + name: "gnss_configuration_from_resource" namespace: "location" - description: "Flag for replacing future elapsedRealtime in JNI" - bug: "314328533" + description: "Flag for GNSS configuration from resource" + bug: "317734846" } diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl index 2eec9b3d4a09..8dfa6be0fd11 100644 --- a/media/java/android/media/IAudioService.aidl +++ b/media/java/android/media/IAudioService.aidl @@ -754,15 +754,16 @@ interface IAudioService { void unregisterLoudnessCodecUpdatesDispatcher(in ILoudnessCodecUpdatesDispatcher dispatcher); - oneway void startLoudnessCodecUpdates(int piid, in List<LoudnessCodecInfo> codecInfoSet); + oneway void startLoudnessCodecUpdates(int sessionId); - oneway void stopLoudnessCodecUpdates(int piid); + oneway void stopLoudnessCodecUpdates(int sessionId); - oneway void addLoudnessCodecInfo(int piid, int mediaCodecHash, in LoudnessCodecInfo codecInfo); + oneway void addLoudnessCodecInfo(int sessionId, int mediaCodecHash, + in LoudnessCodecInfo codecInfo); - oneway void removeLoudnessCodecInfo(int piid, in LoudnessCodecInfo codecInfo); + oneway void removeLoudnessCodecInfo(int sessionId, in LoudnessCodecInfo codecInfo); - PersistableBundle getLoudnessParams(int piid, in LoudnessCodecInfo codecInfo); + PersistableBundle getLoudnessParams(in LoudnessCodecInfo codecInfo); @EnforcePermission("MODIFY_AUDIO_SETTINGS_PRIVILEGED") @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED)") diff --git a/media/java/android/media/ILoudnessCodecUpdatesDispatcher.aidl b/media/java/android/media/ILoudnessCodecUpdatesDispatcher.aidl index 16eaaea38b7f..202242755a97 100644 --- a/media/java/android/media/ILoudnessCodecUpdatesDispatcher.aidl +++ b/media/java/android/media/ILoudnessCodecUpdatesDispatcher.aidl @@ -16,6 +16,7 @@ package android.media; +import android.media.AudioAttributes; import android.os.PersistableBundle; /** @@ -26,6 +27,6 @@ import android.os.PersistableBundle; */ oneway interface ILoudnessCodecUpdatesDispatcher { - void dispatchLoudnessCodecParameterChange(int piid, in PersistableBundle params); + void dispatchLoudnessCodecParameterChange(int sessionId, in PersistableBundle params); }
\ No newline at end of file diff --git a/media/java/android/media/LoudnessCodecConfigurator.java b/media/java/android/media/LoudnessCodecController.java index aadd78328d68..b3e5c52b27b3 100644 --- a/media/java/android/media/LoudnessCodecConfigurator.java +++ b/media/java/android/media/LoudnessCodecController.java @@ -16,13 +16,13 @@ package android.media; -import static android.media.AudioPlaybackConfiguration.PLAYER_PIID_INVALID; import static android.media.LoudnessCodecInfo.CodecMetadataType.CODEC_METADATA_TYPE_MPEG_4; import static android.media.LoudnessCodecInfo.CodecMetadataType.CODEC_METADATA_TYPE_MPEG_D; import static android.media.audio.Flags.FLAG_LOUDNESS_CONFIGURATOR_API; import android.annotation.CallbackExecutor; import android.annotation.FlaggedApi; +import android.media.permission.SafeCloseable; import android.os.Bundle; import android.util.Log; @@ -32,7 +32,6 @@ import androidx.annotation.Nullable; import java.util.HashMap; import java.util.HashSet; -import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; @@ -41,16 +40,21 @@ import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicBoolean; /** - * Class for getting recommended loudness parameter updates for audio decoders, according to the - * encoded format and current audio routing. Those updates can be automatically applied to the - * {@link MediaCodec} instance(s), or be provided to the user. The codec loudness management - * parameter updates are defined by the CTA-2075 standard. - * <p>A new object should be instantiated for each {@link AudioTrack} with the help - * of {@link #create()} or {@link #create(Executor, OnLoudnessCodecUpdateListener)}. + * Class for getting recommended loudness parameter updates for audio decoders as they are used + * to play back media content according to the encoded format and current audio routing. These + * audio decoder updates leverage loudness metadata present in compressed audio streams. They + * ensure the loudness and dynamic range of the content is optimized to the physical + * characteristics of the audio output device (e.g. phone microspeakers vs headphones vs TV + * speakers).Those updates can be automatically applied to the {@link MediaCodec} instance(s), or + * be provided to the user. The codec loudness management parameter updates are computed in + * accordance to the CTA-2075 standard. + * <p>A new object should be instantiated for each audio session + * (see {@link AudioManager#generateAudioSessionId()}) using creator methods {@link #create(int)} or + * {@link #create(int, Executor, OnLoudnessCodecUpdateListener)}. */ @FlaggedApi(FLAG_LOUDNESS_CONFIGURATOR_API) -public class LoudnessCodecConfigurator { - private static final String TAG = "LoudnessCodecConfigurator"; +public class LoudnessCodecController implements SafeCloseable { + private static final String TAG = "LoudnessCodecController"; /** * Listener used for receiving asynchronous loudness metadata updates. @@ -67,6 +71,7 @@ public class LoudnessCodecConfigurator { * directly on the mediaCodec. The listener can modify * these values with their own edits which will be * returned for the mediaCodec configuration + * * @return a Bundle which contains the original computed codecValues * aggregated with user edits. The platform will configure the associated * MediaCodecs with the returned Bundle params. @@ -74,159 +79,116 @@ public class LoudnessCodecConfigurator { @FlaggedApi(FLAG_LOUDNESS_CONFIGURATOR_API) @NonNull default Bundle onLoudnessCodecUpdate(@NonNull MediaCodec mediaCodec, - @NonNull Bundle codecValues) { + @NonNull Bundle codecValues) { return codecValues; } } - @NonNull private final LoudnessCodecDispatcher mLcDispatcher; - - private final Object mConfiguratorLock = new Object(); - - @GuardedBy("mConfiguratorLock") - private AudioTrack mAudioTrack; + @NonNull + private final LoudnessCodecDispatcher mLcDispatcher; - @GuardedBy("mConfiguratorLock") - private final Executor mExecutor; + private final Object mControllerLock = new Object(); - @GuardedBy("mConfiguratorLock") - private final OnLoudnessCodecUpdateListener mListener; + private final int mSessionId; - @GuardedBy("mConfiguratorLock") + @GuardedBy("mControllerLock") private final HashMap<LoudnessCodecInfo, Set<MediaCodec>> mMediaCodecs = new HashMap<>(); /** - * Creates a new instance of {@link LoudnessCodecConfigurator} + * Creates a new instance of {@link LoudnessCodecController} * * <p>This method should be used when the client does not need to alter the * codec loudness parameters before they are applied to the audio decoders. - * Otherwise, use {@link #create(Executor, OnLoudnessCodecUpdateListener)}. + * Otherwise, use {@link #create(int, Executor, OnLoudnessCodecUpdateListener)}. * - * @return the {@link LoudnessCodecConfigurator} instance + * @param sessionId the session ID of the track that will receive data + * from the added {@link MediaCodec}'s + * + * @return the {@link LoudnessCodecController} instance */ @FlaggedApi(FLAG_LOUDNESS_CONFIGURATOR_API) - public static @NonNull LoudnessCodecConfigurator create() { - return new LoudnessCodecConfigurator(new LoudnessCodecDispatcher(AudioManager.getService()), - Executors.newSingleThreadExecutor(), new OnLoudnessCodecUpdateListener() {}); + public static @NonNull LoudnessCodecController create(int sessionId) { + final LoudnessCodecDispatcher dispatcher = new LoudnessCodecDispatcher( + AudioManager.getService()); + final LoudnessCodecController controller = new LoudnessCodecController(dispatcher, + sessionId); + dispatcher.addLoudnessCodecListener(controller, Executors.newSingleThreadExecutor(), + new OnLoudnessCodecUpdateListener() {}); + dispatcher.startLoudnessCodecUpdates(sessionId); + return controller; } /** - * Creates a new instance of {@link LoudnessCodecConfigurator} + * Creates a new instance of {@link LoudnessCodecController} * * <p>This method should be used when the client wants to alter the codec * loudness parameters before they are applied to the audio decoders. - * Otherwise, use {@link #create()}. + * Otherwise, use {@link #create( int)}. * - * @param executor {@link Executor} to handle the callbacks - * @param listener used for receiving updates + * @param sessionId the session ID of the track that will receive data + * from the added {@link MediaCodec}'s + * @param executor {@link Executor} to handle the callbacks + * @param listener used for receiving updates * - * @return the {@link LoudnessCodecConfigurator} instance + * @return the {@link LoudnessCodecController} instance */ @FlaggedApi(FLAG_LOUDNESS_CONFIGURATOR_API) - public static @NonNull LoudnessCodecConfigurator create( + public static @NonNull LoudnessCodecController create( + int sessionId, @NonNull @CallbackExecutor Executor executor, @NonNull OnLoudnessCodecUpdateListener listener) { Objects.requireNonNull(executor, "Executor cannot be null"); Objects.requireNonNull(listener, "OnLoudnessCodecUpdateListener cannot be null"); - return new LoudnessCodecConfigurator(new LoudnessCodecDispatcher(AudioManager.getService()), - executor, listener); + final LoudnessCodecDispatcher dispatcher = new LoudnessCodecDispatcher( + AudioManager.getService()); + final LoudnessCodecController controller = new LoudnessCodecController(dispatcher, + sessionId); + dispatcher.addLoudnessCodecListener(controller, executor, listener); + dispatcher.startLoudnessCodecUpdates(sessionId); + return controller; } /** - * Creates a new instance of {@link LoudnessCodecConfigurator} + * Creates a new instance of {@link LoudnessCodecController} * * <p>This method should be used only in testing * - * @param service interface for communicating with AudioService + * @param sessionId the session ID of the track that will receive data + * from the added {@link MediaCodec}'s * @param executor {@link Executor} to handle the callbacks * @param listener used for receiving updates + * @param service interface for communicating with AudioService * - * @return the {@link LoudnessCodecConfigurator} instance - * + * @return the {@link LoudnessCodecController} instance * @hide */ - public static @NonNull LoudnessCodecConfigurator createForTesting( - @NonNull IAudioService service, + public static @NonNull LoudnessCodecController createForTesting( + int sessionId, @NonNull @CallbackExecutor Executor executor, - @NonNull OnLoudnessCodecUpdateListener listener) { + @NonNull OnLoudnessCodecUpdateListener listener, + @NonNull IAudioService service) { Objects.requireNonNull(service, "IAudioService cannot be null"); Objects.requireNonNull(executor, "Executor cannot be null"); Objects.requireNonNull(listener, "OnLoudnessCodecUpdateListener cannot be null"); - return new LoudnessCodecConfigurator(new LoudnessCodecDispatcher(service), - executor, listener); + final LoudnessCodecDispatcher dispatcher = new LoudnessCodecDispatcher(service); + final LoudnessCodecController controller = new LoudnessCodecController(dispatcher, + sessionId); + dispatcher.addLoudnessCodecListener(controller, executor, listener); + dispatcher.startLoudnessCodecUpdates(sessionId); + return controller; } /** @hide */ - private LoudnessCodecConfigurator(@NonNull LoudnessCodecDispatcher lcDispatcher, - @NonNull @CallbackExecutor Executor executor, - @NonNull OnLoudnessCodecUpdateListener listener) { + private LoudnessCodecController(@NonNull LoudnessCodecDispatcher lcDispatcher, int sessionId) { mLcDispatcher = Objects.requireNonNull(lcDispatcher, "Dispatcher cannot be null"); - mExecutor = Objects.requireNonNull(executor, "Executor cannot be null"); - mListener = Objects.requireNonNull(listener, - "OnLoudnessCodecUpdateListener cannot be null"); - } - - /** - * Sets the {@link AudioTrack} and starts receiving asynchronous updates for - * the registered {@link MediaCodec}s (see {@link #addMediaCodec(MediaCodec)}) - * - * <p>The AudioTrack should be the one that receives audio data from the - * added audio decoders and is used to determine the device routing on which - * the audio streaming will take place. This will directly influence the - * loudness parameters. - * <p>After calling this method the framework will compute the initial set of - * parameters which will be applied to the registered codecs/returned to the - * listener for modification. - * - * @param audioTrack the track that will receive audio data from the provided - * audio decoders. In case this is {@code null} this - * method will have the effect of clearing the existing set - * {@link AudioTrack} and will stop receiving asynchronous - * loudness updates - */ - @FlaggedApi(FLAG_LOUDNESS_CONFIGURATOR_API) - public void setAudioTrack(@Nullable AudioTrack audioTrack) { - List<LoudnessCodecInfo> codecInfos; - int piid = PLAYER_PIID_INVALID; - int oldPiid = PLAYER_PIID_INVALID; - synchronized (mConfiguratorLock) { - if (mAudioTrack != null && mAudioTrack == audioTrack) { - Log.v(TAG, "Loudness configurator already started for piid: " - + mAudioTrack.getPlayerIId()); - return; - } - - codecInfos = getLoudnessCodecInfoList_l(); - if (mAudioTrack != null) { - oldPiid = mAudioTrack.getPlayerIId(); - mLcDispatcher.removeLoudnessCodecListener(this); - } - if (audioTrack != null) { - piid = audioTrack.getPlayerIId(); - mLcDispatcher.addLoudnessCodecListener(this, mExecutor, mListener); - } - - mAudioTrack = audioTrack; - } - - if (oldPiid != PLAYER_PIID_INVALID) { - Log.v(TAG, "Loudness configurator stopping updates for piid: " + oldPiid); - mLcDispatcher.stopLoudnessCodecUpdates(oldPiid); - } - if (piid != PLAYER_PIID_INVALID) { - Log.v(TAG, "Loudness configurator starting updates for piid: " + piid); - mLcDispatcher.startLoudnessCodecUpdates(piid, codecInfos); - } + mSessionId = sessionId; } /** - * Adds a new {@link MediaCodec} that will stream data to an {@link AudioTrack} - * which the client sets - * (see {@link LoudnessCodecConfigurator#setAudioTrack(AudioTrack)}). - * - * <p>This method can be called while asynchronous updates are live. + * Adds a new {@link MediaCodec} that will stream data to a player + * which uses {@link #mSessionId}. * * <p>No new element will be added if the passed {@code mediaCodec} was * previously added. @@ -234,23 +196,22 @@ public class LoudnessCodecConfigurator { * @param mediaCodec the codec to start receiving asynchronous loudness * updates. The codec has to be in a configured or started * state in order to add it for loudness updates. + * @return {@code false} if the {@code mediaCodec} was not configured or does + * not contain loudness metadata, {@code true} otherwise. * @throws IllegalArgumentException if the same {@code mediaCodec} was already * added before. - * @return {@code false} if the {@code mediaCodec} was not configured or does - * not contain loudness metadata, {@code true} otherwise. */ @FlaggedApi(FLAG_LOUDNESS_CONFIGURATOR_API) public boolean addMediaCodec(@NonNull MediaCodec mediaCodec) { final MediaCodec mc = Objects.requireNonNull(mediaCodec, "MediaCodec for addMediaCodec cannot be null"); - int piid = PLAYER_PIID_INVALID; final LoudnessCodecInfo mcInfo = getCodecInfo(mc); if (mcInfo == null) { Log.v(TAG, "Could not extract codec loudness information"); return false; } - synchronized (mConfiguratorLock) { + synchronized (mControllerLock) { final AtomicBoolean containsCodec = new AtomicBoolean(false); Set<MediaCodec> newSet = mMediaCodecs.computeIfPresent(mcInfo, (info, codecSet) -> { containsCodec.set(!codecSet.add(mc)); @@ -263,16 +224,12 @@ public class LoudnessCodecConfigurator { } if (containsCodec.get()) { throw new IllegalArgumentException( - "Loudness configurator already added " + mediaCodec); - } - if (mAudioTrack != null) { - piid = mAudioTrack.getPlayerIId(); + "Loudness controller already added " + mediaCodec); } } - if (piid != PLAYER_PIID_INVALID) { - mLcDispatcher.addLoudnessCodecInfo(piid, mediaCodec.hashCode(), mcInfo); - } + mLcDispatcher.addLoudnessCodecInfo(mSessionId, mediaCodec.hashCode(), + mcInfo); return true; } @@ -291,7 +248,6 @@ public class LoudnessCodecConfigurator { */ @FlaggedApi(FLAG_LOUDNESS_CONFIGURATOR_API) public void removeMediaCodec(@NonNull MediaCodec mediaCodec) { - int piid = PLAYER_PIID_INVALID; LoudnessCodecInfo mcInfo; AtomicBoolean removedMc = new AtomicBoolean(false); AtomicBoolean removeInfo = new AtomicBoolean(false); @@ -302,10 +258,7 @@ public class LoudnessCodecConfigurator { if (mcInfo == null) { throw new IllegalArgumentException("Could not extract codec loudness information"); } - synchronized (mConfiguratorLock) { - if (mAudioTrack != null) { - piid = mAudioTrack.getPlayerIId(); - } + synchronized (mControllerLock) { mMediaCodecs.computeIfPresent(mcInfo, (format, mcs) -> { removedMc.set(mcs.remove(mediaCodec)); if (mcs.isEmpty()) { @@ -317,68 +270,81 @@ public class LoudnessCodecConfigurator { }); if (!removedMc.get()) { throw new IllegalArgumentException( - "Loudness configurator does not contain " + mediaCodec); + "Loudness controller does not contain " + mediaCodec); } } - if (piid != PLAYER_PIID_INVALID && removeInfo.get()) { - mLcDispatcher.removeLoudnessCodecInfo(piid, mcInfo); + if (removeInfo.get()) { + mLcDispatcher.removeLoudnessCodecInfo(mSessionId, mcInfo); } } /** - * Gets synchronous loudness updates when no listener is required. The provided - * {@link MediaCodec} streams audio data to the passed {@link AudioTrack}. + * Returns the loudness parameters of the registered audio decoders + * + * <p>Those parameters may have been automatically applied if the + * {@code LoudnessCodecController} was created with {@link #create(int)}, or they are the + * parameters that have been sent to the {@link OnLoudnessCodecUpdateListener} if using a + * codec update listener. * - * @param audioTrack track that receives audio data from the passed - * {@link MediaCodec} - * @param mediaCodec codec that decodes loudness annotated data for the passed - * {@link AudioTrack} + * @param mediaCodec codec that decodes loudness annotated data. Has to be added + * with {@link #addMediaCodec(MediaCodec)} before calling this + * method + * @throws IllegalArgumentException if the passed {@link MediaCodec} was not + * added before calling this method * - * @return the {@link Bundle} containing the current loudness parameters. Caller is - * responsible to update the {@link MediaCodec} + * @return the {@link Bundle} containing the current loudness parameters. */ @FlaggedApi(FLAG_LOUDNESS_CONFIGURATOR_API) @NonNull - public Bundle getLoudnessCodecParams(@NonNull AudioTrack audioTrack, - @NonNull MediaCodec mediaCodec) { - Objects.requireNonNull(audioTrack, "Passed audio track cannot be null"); + public Bundle getLoudnessCodecParams(@NonNull MediaCodec mediaCodec) { + Objects.requireNonNull(mediaCodec, "MediaCodec cannot be null"); LoudnessCodecInfo codecInfo = getCodecInfo(mediaCodec); if (codecInfo == null) { - return new Bundle(); + throw new IllegalArgumentException("MediaCodec does not have valid codec information"); } - return mLcDispatcher.getLoudnessCodecParams(audioTrack.getPlayerIId(), codecInfo); + synchronized (mControllerLock) { + final Set<MediaCodec> codecs = mMediaCodecs.get(codecInfo); + if (codecs == null || !codecs.contains(mediaCodec)) { + throw new IllegalArgumentException( + "MediaCodec was not added for loudness annotation"); + } + } + + return mLcDispatcher.getLoudnessCodecParams(codecInfo); } - /** @hide */ - /*package*/ int getAssignedTrackPiid() { - int piid = PLAYER_PIID_INVALID; + /** + * Stops any loudness updates and frees up the resources. + */ + @FlaggedApi(FLAG_LOUDNESS_CONFIGURATOR_API) + public void release() { + close(); + } - synchronized (mConfiguratorLock) { - if (mAudioTrack == null) { - return piid; - } - piid = mAudioTrack.getPlayerIId(); + /** @hide */ + @Override + public void close() { + synchronized (mControllerLock) { + mMediaCodecs.clear(); } + mLcDispatcher.stopLoudnessCodecUpdates(mSessionId); + } - return piid; + /** @hide */ + /*package*/ int getSessionId() { + return mSessionId; } /** @hide */ /*package*/ Map<LoudnessCodecInfo, Set<MediaCodec>> getRegisteredMediaCodecs() { - synchronized (mConfiguratorLock) { + synchronized (mControllerLock) { return mMediaCodecs; } } - @GuardedBy("mConfiguratorLock") - private List<LoudnessCodecInfo> getLoudnessCodecInfoList_l() { - return mMediaCodecs.values().stream().flatMap(listMc -> listMc.stream().map( - LoudnessCodecConfigurator::getCodecInfo)).toList(); - } - @Nullable private static LoudnessCodecInfo getCodecInfo(@NonNull MediaCodec mediaCodec) { LoudnessCodecInfo lci = new LoudnessCodecInfo(); diff --git a/media/java/android/media/LoudnessCodecDispatcher.java b/media/java/android/media/LoudnessCodecDispatcher.java index b546a81b0498..46be54be55ec 100644 --- a/media/java/android/media/LoudnessCodecDispatcher.java +++ b/media/java/android/media/LoudnessCodecDispatcher.java @@ -21,7 +21,7 @@ import static android.media.MediaFormat.KEY_AAC_DRC_HEAVY_COMPRESSION; import static android.media.MediaFormat.KEY_AAC_DRC_TARGET_REFERENCE_LEVEL; import android.annotation.CallbackExecutor; -import android.media.LoudnessCodecConfigurator.OnLoudnessCodecUpdateListener; +import android.media.LoudnessCodecController.OnLoudnessCodecUpdateListener; import android.os.Bundle; import android.os.PersistableBundle; import android.os.RemoteException; @@ -32,7 +32,6 @@ import androidx.annotation.NonNull; import java.util.HashMap; import java.util.Iterator; -import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Objects; @@ -59,7 +58,7 @@ public class LoudnessCodecDispatcher implements CallbackUtil.DispatcherStub { private final Object mLock = new Object(); @GuardedBy("mLock") - private final HashMap<OnLoudnessCodecUpdateListener, LoudnessCodecConfigurator> + private final HashMap<OnLoudnessCodecUpdateListener, LoudnessCodecController> mConfiguratorListener = new HashMap<>(); public static synchronized LoudnessCodecUpdatesDispatcherStub getInstance() { @@ -72,16 +71,16 @@ public class LoudnessCodecDispatcher implements CallbackUtil.DispatcherStub { private LoudnessCodecUpdatesDispatcherStub() {} @Override - public void dispatchLoudnessCodecParameterChange(int piid, PersistableBundle params) { + public void dispatchLoudnessCodecParameterChange(int sessionId, PersistableBundle params) { if (DEBUG) { - Log.d(TAG, "dispatchLoudnessCodecParameterChange for piid " + piid + Log.d(TAG, "dispatchLoudnessCodecParameterChange for sessionId " + sessionId + " persistable bundle: " + params); } mLoudnessListenerMgr.callListeners(listener -> { synchronized (mLock) { mConfiguratorListener.computeIfPresent(listener, (l, lcConfig) -> { // send the appropriate bundle for the user to update - if (lcConfig.getAssignedTrackPiid() == piid) { + if (lcConfig.getSessionId() == sessionId) { final Map<LoudnessCodecInfo, Set<MediaCodec>> mediaCodecsMap = lcConfig.getRegisteredMediaCodecs(); for (LoudnessCodecInfo codecInfo : mediaCodecsMap.keySet()) { @@ -111,7 +110,12 @@ public class LoudnessCodecDispatcher implements CallbackUtil.DispatcherStub { bundle)); if (!bundle.isDefinitelyEmpty()) { - mediaCodec.setParameters(bundle); + try { + mediaCodec.setParameters(bundle); + } catch (IllegalStateException e) { + Log.w(TAG, "Cannot set loudness bundle on media codec " + + mediaCodec); + } } if (canBreak) { break; @@ -145,7 +149,7 @@ public class LoudnessCodecDispatcher implements CallbackUtil.DispatcherStub { } void addLoudnessCodecListener(@NonNull CallbackUtil.DispatcherStub dispatcher, - @NonNull LoudnessCodecConfigurator configurator, + @NonNull LoudnessCodecController configurator, @NonNull @CallbackExecutor Executor executor, @NonNull OnLoudnessCodecUpdateListener listener) { Objects.requireNonNull(configurator); @@ -160,15 +164,15 @@ public class LoudnessCodecDispatcher implements CallbackUtil.DispatcherStub { } } - void removeLoudnessCodecListener(@NonNull LoudnessCodecConfigurator configurator) { + void removeLoudnessCodecListener(@NonNull LoudnessCodecController configurator) { Objects.requireNonNull(configurator); OnLoudnessCodecUpdateListener listenerToRemove = null; synchronized (mLock) { - Iterator<Entry<OnLoudnessCodecUpdateListener, LoudnessCodecConfigurator>> iterator = + Iterator<Entry<OnLoudnessCodecUpdateListener, LoudnessCodecController>> iterator = mConfiguratorListener.entrySet().iterator(); while (iterator.hasNext()) { - Entry<OnLoudnessCodecUpdateListener, LoudnessCodecConfigurator> e = + Entry<OnLoudnessCodecUpdateListener, LoudnessCodecController> e = iterator.next(); if (e.getValue() == configurator) { final OnLoudnessCodecUpdateListener listener = e.getKey(); @@ -208,7 +212,7 @@ public class LoudnessCodecDispatcher implements CallbackUtil.DispatcherStub { } /** @hide */ - public void addLoudnessCodecListener(@NonNull LoudnessCodecConfigurator configurator, + public void addLoudnessCodecListener(@NonNull LoudnessCodecController configurator, @NonNull @CallbackExecutor Executor executor, @NonNull OnLoudnessCodecUpdateListener listener) { LoudnessCodecUpdatesDispatcherStub.getInstance().addLoudnessCodecListener(this, @@ -216,52 +220,52 @@ public class LoudnessCodecDispatcher implements CallbackUtil.DispatcherStub { } /** @hide */ - public void removeLoudnessCodecListener(@NonNull LoudnessCodecConfigurator configurator) { + public void removeLoudnessCodecListener(@NonNull LoudnessCodecController configurator) { LoudnessCodecUpdatesDispatcherStub.getInstance().removeLoudnessCodecListener(configurator); } /** @hide */ - public void startLoudnessCodecUpdates(int piid, List<LoudnessCodecInfo> codecInfoList) { + public void startLoudnessCodecUpdates(int sessionId) { try { - mAudioService.startLoudnessCodecUpdates(piid, codecInfoList); + mAudioService.startLoudnessCodecUpdates(sessionId); } catch (RemoteException e) { e.rethrowFromSystemServer(); } } /** @hide */ - public void stopLoudnessCodecUpdates(int piid) { + public void stopLoudnessCodecUpdates(int sessionId) { try { - mAudioService.stopLoudnessCodecUpdates(piid); + mAudioService.stopLoudnessCodecUpdates(sessionId); } catch (RemoteException e) { e.rethrowFromSystemServer(); } } /** @hide */ - public void addLoudnessCodecInfo(int piid, int mediaCodecHash, + public void addLoudnessCodecInfo(int sessionId, int mediaCodecHash, @NonNull LoudnessCodecInfo mcInfo) { try { - mAudioService.addLoudnessCodecInfo(piid, mediaCodecHash, mcInfo); + mAudioService.addLoudnessCodecInfo(sessionId, mediaCodecHash, mcInfo); } catch (RemoteException e) { e.rethrowFromSystemServer(); } } /** @hide */ - public void removeLoudnessCodecInfo(int piid, @NonNull LoudnessCodecInfo mcInfo) { + public void removeLoudnessCodecInfo(int sessionId, @NonNull LoudnessCodecInfo mcInfo) { try { - mAudioService.removeLoudnessCodecInfo(piid, mcInfo); + mAudioService.removeLoudnessCodecInfo(sessionId, mcInfo); } catch (RemoteException e) { e.rethrowFromSystemServer(); } } /** @hide */ - public Bundle getLoudnessCodecParams(int piid, @NonNull LoudnessCodecInfo mcInfo) { + public Bundle getLoudnessCodecParams(@NonNull LoudnessCodecInfo mcInfo) { Bundle loudnessParams = null; try { - loudnessParams = new Bundle(mAudioService.getLoudnessParams(piid, mcInfo)); + loudnessParams = new Bundle(mAudioService.getLoudnessParams(mcInfo)); } catch (RemoteException e) { e.rethrowFromSystemServer(); } diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java index 587e35b4b1fc..5e40eee26886 100644 --- a/media/java/android/media/MediaFormat.java +++ b/media/java/android/media/MediaFormat.java @@ -17,6 +17,7 @@ package android.media; import static com.android.media.codec.flags.Flags.FLAG_CODEC_IMPORTANCE; +import static com.android.media.codec.flags.Flags.FLAG_LARGE_AUDIO_FRAME; import android.annotation.FlaggedApi; import android.annotation.IntDef; @@ -121,6 +122,10 @@ import java.util.stream.Collectors; * <tr><td>{@link #KEY_MPEGH_REFERENCE_CHANNEL_LAYOUT}</td> * <td>Integer</td><td><b>decoder-only</b>, optional, if content is MPEG-H audio, * specifies the preferred reference channel layout of the stream.</td></tr> + * <tr><td>{@link #KEY_MAX_BUFFER_BATCH_OUTPUT_SIZE}</td><td>Integer</td><td>optional, used with + * large audio frame support, specifies max size of output buffer in bytes.</td></tr> + * <tr><td>{@link #KEY_BUFFER_BATCH_THRESHOLD_OUTPUT_SIZE}</td><td>Integer</td><td>optional, + * used with large audio frame support, specifies threshold output size in bytes.</td></tr> * </table> * * Subtitle formats have the following keys: @@ -459,6 +464,50 @@ public final class MediaFormat { public static final String KEY_MAX_INPUT_SIZE = "max-input-size"; /** + * A key describing the maximum output buffer size in bytes when using + * large buffer mode containing multiple access units. + * + * When not-set - codec functions with one access-unit per frame. + * When set less than the size of two access-units - will make codec + * operate in single access-unit per output frame. + * When set to a value too big - The component or the framework will + * override this value to a reasonable max size not exceeding typical + * 10 seconds of data (device dependent) when set to a value larger than + * that. The value final value used will be returned in the output format. + * + * The associated value is an integer + * + * @see FEATURE_MultipleFrames + */ + @FlaggedApi(FLAG_LARGE_AUDIO_FRAME) + public static final String KEY_BUFFER_BATCH_MAX_OUTPUT_SIZE = "buffer-batch-max-output-size"; + + /** + * A key describing the threshold output size in bytes when using large buffer + * mode containing multiple access units. + * + * This is an optional parameter. + * + * If not set - the component can set this to a reasonable value. + * If set larger than max size, the components will + * clip this setting to maximum buffer batching output size. + * + * The component will return a partial output buffer if the output buffer reaches or + * surpass this limit. + * + * Threshold size should be always less or equal to KEY_MAX_BUFFER_BATCH_OUTPUT_SIZE. + * The final setting of this value as determined by the component will be returned + * in the output format + * + * The associated value is an integer + * + * @see FEATURE_MultipleFrames + */ + @FlaggedApi(FLAG_LARGE_AUDIO_FRAME) + public static final String KEY_BUFFER_BATCH_THRESHOLD_OUTPUT_SIZE = + "buffer-batch-threshold-output-size"; + + /** * A key describing the pixel aspect ratio width. * The associated value is an integer */ diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java index 8e9c07996f83..a0f8ae5defeb 100644 --- a/media/java/android/media/MediaPlayer.java +++ b/media/java/android/media/MediaPlayer.java @@ -1154,6 +1154,7 @@ public class MediaPlayer extends PlayerBase setDataSource(afd); return true; } catch (NullPointerException | SecurityException | IOException ex) { + Log.w(TAG, "Error setting data source via ContentResolver", ex); return false; } } diff --git a/media/java/android/media/MediaRouter2.java b/media/java/android/media/MediaRouter2.java index 17f25255fd4b..691aa7784d7a 100644 --- a/media/java/android/media/MediaRouter2.java +++ b/media/java/android/media/MediaRouter2.java @@ -196,8 +196,8 @@ public final class MediaRouter2 { * Manifest.permission#MEDIA_CONTENT_CONTROL MEDIA_CONTENT_CONTROL} permission. * @hide */ - // TODO (b/311711420): Deprecate once #getInstance(Context, Looper, String, UserHandle) - // reaches public SDK. + // TODO (b/311711420): Deprecate once #getInstance(Context, String, UserHandle) reaches public + // SDK. @SystemApi @RequiresPermission(Manifest.permission.MEDIA_CONTENT_CONTROL) @Nullable @@ -206,7 +206,7 @@ public final class MediaRouter2 { // Capturing the IAE here to not break nullability. try { return findOrCreateProxyInstanceForCallingUser( - context, Looper.getMainLooper(), clientPackageName, context.getUser()); + context, clientPackageName, context.getUser()); } catch (IllegalArgumentException ex) { Log.e(TAG, "Package " + clientPackageName + " not found. Ignoring."); return null; @@ -217,8 +217,6 @@ public final class MediaRouter2 { * Returns a proxy MediaRouter2 instance that allows you to control the routing of an app * specified by {@code clientPackageName} and {@code user}. * - * <p>You can specify any {@link Looper} of choice on which internal state updates will run. - * * <p>Proxy MediaRouter2 instances operate differently than regular MediaRouter2 instances: * * <ul> @@ -237,7 +235,6 @@ public final class MediaRouter2 { * </ul> * * @param context The {@link Context} of the caller. - * @param looper The {@link Looper} on which to process internal state changes. * @param clientPackageName The package name of the app you want to control the routing of. * @param user The {@link UserHandle} of the user running the app for which to get the proxy * router instance. Must match {@link Process#myUserHandle()} if the caller doesn't hold @@ -255,10 +252,9 @@ public final class MediaRouter2 { @NonNull public static MediaRouter2 getInstance( @NonNull Context context, - @NonNull Looper looper, @NonNull String clientPackageName, @NonNull UserHandle user) { - return findOrCreateProxyInstanceForCallingUser(context, looper, clientPackageName, user); + return findOrCreateProxyInstanceForCallingUser(context, clientPackageName, user); } /** @@ -270,9 +266,8 @@ public final class MediaRouter2 { */ @NonNull private static MediaRouter2 findOrCreateProxyInstanceForCallingUser( - Context context, Looper looper, String clientPackageName, UserHandle user) { + Context context, String clientPackageName, UserHandle user) { Objects.requireNonNull(context, "context must not be null"); - Objects.requireNonNull(looper, "looper must not be null"); Objects.requireNonNull(user, "user must not be null"); if (TextUtils.isEmpty(clientPackageName)) { @@ -284,7 +279,8 @@ public final class MediaRouter2 { synchronized (sSystemRouterLock) { MediaRouter2 instance = sAppToProxyRouterMap.get(key); if (instance == null) { - instance = new MediaRouter2(context, looper, clientPackageName, user); + instance = + new MediaRouter2(context, Looper.getMainLooper(), clientPackageName, user); // Register proxy router after instantiation to avoid race condition. ((ProxyMediaRouter2Impl) instance.mImpl).registerProxyRouter(); sAppToProxyRouterMap.put(key, instance); @@ -3109,9 +3105,8 @@ public final class MediaRouter2 { mStub, mDiscoveryPreference); } - if (mRouteCallbackRecords.isEmpty() && mNonSystemRoutingControllers.isEmpty()) { - unregisterRouterStubLocked(); - } + unregisterRouterStubIfNeededLocked(); + } catch (RemoteException ex) { Log.e(TAG, "unregisterRouteCallback: Unable to set discovery request.", ex); } @@ -3319,13 +3314,12 @@ public final class MediaRouter2 { obtainMessage(MediaRouter2::notifyStop, MediaRouter2.this, controller)); } - if (mRouteCallbackRecords.isEmpty() && mNonSystemRoutingControllers.isEmpty()) { - try { - unregisterRouterStubLocked(); - } catch (RemoteException ex) { - ex.rethrowFromSystemServer(); - } + try { + unregisterRouterStubIfNeededLocked(); + } catch (RemoteException ex) { + ex.rethrowFromSystemServer(); } + } } @@ -3339,8 +3333,10 @@ public final class MediaRouter2 { } @GuardedBy("mLock") - private void unregisterRouterStubLocked() throws RemoteException { - if (mStub != null) { + private void unregisterRouterStubIfNeededLocked() throws RemoteException { + if (mStub != null + && mRouteCallbackRecords.isEmpty() + && mNonSystemRoutingControllers.isEmpty()) { mMediaRouterService.unregisterRouter2(mStub); mStub = null; } diff --git a/media/java/android/media/audiofx/Virtualizer.java b/media/java/android/media/audiofx/Virtualizer.java index 74b6fc13ade4..71147f4becb5 100644 --- a/media/java/android/media/audiofx/Virtualizer.java +++ b/media/java/android/media/audiofx/Virtualizer.java @@ -46,6 +46,11 @@ import java.util.StringTokenizer; * <p>See {@link android.media.MediaPlayer#getAudioSessionId()} for details on audio sessions. * <p>See {@link android.media.audiofx.AudioEffect} class for more details on controlling * audio effects. + * + * @deprecated use the {@link android.media.Spatializer} class to query the capabilities of the + * platform with regards to spatialization, a different name for audio channel virtualization, + * and the {@link android.media.AudioAttributes.Builder#setSpatializationBehavior(int)} to + * characterize how you want your content to be played when spatialization is supported. */ public class Virtualizer extends AudioEffect { diff --git a/media/java/android/media/tv/BroadcastInfoRequest.java b/media/java/android/media/tv/BroadcastInfoRequest.java index cbd8c1fd53cd..694756c3f1a3 100644 --- a/media/java/android/media/tv/BroadcastInfoRequest.java +++ b/media/java/android/media/tv/BroadcastInfoRequest.java @@ -32,7 +32,8 @@ import java.lang.annotation.RetentionPolicy; public abstract class BroadcastInfoRequest implements Parcelable { /** @hide */ @Retention(RetentionPolicy.SOURCE) - @IntDef({REQUEST_OPTION_REPEAT, REQUEST_OPTION_AUTO_UPDATE}) + @IntDef({REQUEST_OPTION_REPEAT, REQUEST_OPTION_AUTO_UPDATE, + REQUEST_OPTION_ONEWAY, REQUEST_OPTION_ONESHOT}) public @interface RequestOption {} /** @@ -47,6 +48,18 @@ public abstract class BroadcastInfoRequest implements Parcelable { * first time, new values are detected. */ public static final int REQUEST_OPTION_AUTO_UPDATE = 1; + /** + * Request option: one-way + * <p> With this option, no response is expected after sending the request. + * @hide + */ + public static final int REQUEST_OPTION_ONEWAY = 2; + /** + * Request option: one-shot + * <p> With this option, only one response will be given per request. + * @hide + */ + public static final int REQUEST_OPTION_ONESHOT = 3; public static final @NonNull Parcelable.Creator<BroadcastInfoRequest> CREATOR = new Parcelable.Creator<BroadcastInfoRequest>() { diff --git a/media/java/android/media/tv/ITvInputClient.aidl b/media/java/android/media/tv/ITvInputClient.aidl index 0f8a00a3c7d9..897827750d4e 100644 --- a/media/java/android/media/tv/ITvInputClient.aidl +++ b/media/java/android/media/tv/ITvInputClient.aidl @@ -44,6 +44,7 @@ oneway interface ITvInputClient { void onTrackSelected(int type, in String trackId, int seq); void onVideoAvailable(int seq); void onVideoUnavailable(int reason, int seq); + void onVideoFreezeUpdated(boolean isFrozen, int seq); void onContentAllowed(int seq); void onContentBlocked(in String rating, int seq); void onLayoutSurface(int left, int top, int right, int bottom, int seq); diff --git a/media/java/android/media/tv/ITvInputSessionCallback.aidl b/media/java/android/media/tv/ITvInputSessionCallback.aidl index a52e9a572dca..8e2702a50662 100644 --- a/media/java/android/media/tv/ITvInputSessionCallback.aidl +++ b/media/java/android/media/tv/ITvInputSessionCallback.aidl @@ -41,6 +41,7 @@ oneway interface ITvInputSessionCallback { void onTrackSelected(int type, in String trackId); void onVideoAvailable(); void onVideoUnavailable(int reason); + void onVideoFreezeUpdated(boolean isFrozen); void onContentAllowed(); void onContentBlocked(in String rating); void onLayoutSurface(int left, int top, int right, int bottom); diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java index 51b2542688a6..caddd8ad674f 100644 --- a/media/java/android/media/tv/TvInputManager.java +++ b/media/java/android/media/tv/TvInputManager.java @@ -740,6 +740,15 @@ public final class TvInputManager { } /** + * This is called when the video freeze state has been updated. + * If {@code true}, the video is frozen on the last frame while audio playback continues. + * @param session A {@link TvInputManager.Session} associated with this callback. + * @param isFrozen Whether the video is frozen + */ + public void onVideoFreezeUpdated(Session session, boolean isFrozen) { + } + + /** * This is called when the current program content turns out to be allowed to watch since * its content rating is not blocked by parental controls. * @@ -1030,6 +1039,19 @@ public final class TvInputManager { }); } + void postVideoFreezeUpdated(boolean isFrozen) { + mHandler.post(new Runnable() { + @Override + public void run() { + mSessionCallback.onVideoFreezeUpdated(mSession, isFrozen); + if (mSession.mIAppNotificationEnabled + && mSession.getInteractiveAppSession() != null) { + mSession.getInteractiveAppSession().notifyVideoFreezeUpdated(isFrozen); + } + } + }); + } + void postContentAllowed() { mHandler.post(new Runnable() { @Override @@ -1546,6 +1568,18 @@ public final class TvInputManager { } @Override + public void onVideoFreezeUpdated(boolean isFrozen, int seq) { + synchronized (mSessionCallbackRecordMap) { + SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq); + if (record == null) { + Log.e(TAG, "Callback not found for seq " + seq); + return; + } + record.postVideoFreezeUpdated(isFrozen); + } + } + + @Override public void onContentAllowed(int seq) { synchronized (mSessionCallbackRecordMap) { SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq); diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java index 76d8e50f94be..6301a27bac4d 100644 --- a/media/java/android/media/tv/TvInputService.java +++ b/media/java/android/media/tv/TvInputService.java @@ -763,6 +763,34 @@ public abstract class TvInputService extends Service { } /** + * Informs the application that the video freeze state has been updated. + * + * When {@code true}, the video is frozen on the last frame but audio playback remains + * active. + * + * @param isFrozen Whether or not the video is frozen + * @hide + */ + public void notifyVideoFreezeUpdated(boolean isFrozen) { + executeOrPostRunnableOnMainThread(new Runnable() { + @MainThread + @Override + public void run() { + try { + if (DEBUG) { + Log.d(TAG, "notifyVideoFreezeUpdated"); + } + if (mSessionCallback != null) { + mSessionCallback.onVideoFreezeUpdated(isFrozen); + } + } catch (RemoteException e) { + Log.e(TAG, "error in notifyVideoFreezeUpdated", e); + } + } + }); + } + + /** * Sends an updated list of all audio presentations available from a Next Generation Audio * service. This is used by the framework to maintain the audio presentation information for * a given track of {@link TvTrackInfo#TYPE_AUDIO}, which in turn is used by diff --git a/media/java/android/media/tv/interactive/ITvInteractiveAppManager.aidl b/media/java/android/media/tv/interactive/ITvInteractiveAppManager.aidl index 4316d053a275..0f58b29247bb 100644 --- a/media/java/android/media/tv/interactive/ITvInteractiveAppManager.aidl +++ b/media/java/android/media/tv/interactive/ITvInteractiveAppManager.aidl @@ -88,6 +88,7 @@ interface ITvInteractiveAppManager { void notifyTracksChanged(in IBinder sessionToken, in List<TvTrackInfo> tracks, int userId); void notifyVideoAvailable(in IBinder sessionToken, int userId); void notifyVideoUnavailable(in IBinder sessionToken, int reason, int userId); + void notifyVideoFreezeUpdated(in IBinder sessionToken, boolean isFrozen, int userId); void notifyContentAllowed(in IBinder sessionToken, int userId); void notifyContentBlocked(in IBinder sessionToken, in String rating, int userId); void notifySignalStrength(in IBinder sessionToken, int stength, int userId); diff --git a/media/java/android/media/tv/interactive/ITvInteractiveAppSession.aidl b/media/java/android/media/tv/interactive/ITvInteractiveAppSession.aidl index ba7cf13a7a1d..06808c9ff915 100644 --- a/media/java/android/media/tv/interactive/ITvInteractiveAppSession.aidl +++ b/media/java/android/media/tv/interactive/ITvInteractiveAppSession.aidl @@ -67,6 +67,7 @@ oneway interface ITvInteractiveAppSession { void notifyTracksChanged(in List<TvTrackInfo> tracks); void notifyVideoAvailable(); void notifyVideoUnavailable(int reason); + void notifyVideoFreezeUpdated(boolean isFrozen); void notifyContentAllowed(); void notifyContentBlocked(in String rating); void notifySignalStrength(int strength); diff --git a/media/java/android/media/tv/interactive/ITvInteractiveAppSessionWrapper.java b/media/java/android/media/tv/interactive/ITvInteractiveAppSessionWrapper.java index 518b08a93f95..77730aa46d0a 100644 --- a/media/java/android/media/tv/interactive/ITvInteractiveAppSessionWrapper.java +++ b/media/java/android/media/tv/interactive/ITvInteractiveAppSessionWrapper.java @@ -103,6 +103,7 @@ public class ITvInteractiveAppSessionWrapper private static final int DO_SEND_TIME_SHIFT_MODE = 46; private static final int DO_SEND_AVAILABLE_SPEEDS = 47; private static final int DO_SEND_SELECTED_TRACK_INFO = 48; + private static final int DO_NOTIFY_VIDEO_FREEZE_UPDATED = 49; private final HandlerCaller mCaller; private Session mSessionImpl; @@ -364,6 +365,10 @@ public class ITvInteractiveAppSessionWrapper args.recycle(); break; } + case DO_NOTIFY_VIDEO_FREEZE_UPDATED: { + mSessionImpl.notifyVideoFreezeUpdated((Boolean) msg.obj); + break; + } default: { Log.w(TAG, "Unhandled message code: " + msg.what); break; @@ -552,6 +557,12 @@ public class ITvInteractiveAppSessionWrapper } @Override + public void notifyVideoFreezeUpdated(boolean isFrozen) { + mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_NOTIFY_VIDEO_FREEZE_UPDATED, + isFrozen)); + } + + @Override public void notifyContentAllowed() { mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_NOTIFY_CONTENT_ALLOWED)); } diff --git a/media/java/android/media/tv/interactive/TvInteractiveAppManager.java b/media/java/android/media/tv/interactive/TvInteractiveAppManager.java index bf4379f470d8..8a340f6862bb 100755 --- a/media/java/android/media/tv/interactive/TvInteractiveAppManager.java +++ b/media/java/android/media/tv/interactive/TvInteractiveAppManager.java @@ -1731,6 +1731,22 @@ public final class TvInteractiveAppManager { } /** + * Notifies Interactive app session when the video freeze state is updated + * @param isFrozen Whether or not the video is frozen + */ + public void notifyVideoFreezeUpdated(boolean isFrozen) { + if (mToken == null) { + Log.w(TAG, "The session has been already released"); + return; + } + try { + mService.notifyVideoFreezeUpdated(mToken, isFrozen, mUserId); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** * Notifies Interactive APP session when content is allowed. */ public void notifyContentAllowed() { diff --git a/media/java/android/media/tv/interactive/TvInteractiveAppService.java b/media/java/android/media/tv/interactive/TvInteractiveAppService.java index 79364034ac2a..5247a0ebe6e0 100755 --- a/media/java/android/media/tv/interactive/TvInteractiveAppService.java +++ b/media/java/android/media/tv/interactive/TvInteractiveAppService.java @@ -882,6 +882,15 @@ public abstract class TvInteractiveAppService extends Service { } /** + * Called when video becomes frozen or unfrozen. Audio playback will continue while + * video will be frozen to the last frame if {@code true}. + * @param isFrozen Whether or not the video is frozen. + * @hide + */ + public void onVideoFreezeUpdated(boolean isFrozen) { + } + + /** * Called when content is allowed. */ public void onContentAllowed() { @@ -1770,6 +1779,13 @@ public abstract class TvInteractiveAppService extends Service { onVideoUnavailable(reason); } + void notifyVideoFreezeUpdated(boolean isFrozen) { + if (DEBUG) { + Log.d(TAG, "notifyVideoFreezeUpdated (isFrozen=" + isFrozen + ")"); + } + onVideoFreezeUpdated(isFrozen); + } + void notifyContentAllowed() { if (DEBUG) { Log.d(TAG, "notifyContentAllowed"); diff --git a/media/java/android/media/tv/interactive/TvInteractiveAppView.java b/media/java/android/media/tv/interactive/TvInteractiveAppView.java index 40a12e4db4cc..5bb61c261ae2 100755 --- a/media/java/android/media/tv/interactive/TvInteractiveAppView.java +++ b/media/java/android/media/tv/interactive/TvInteractiveAppView.java @@ -719,6 +719,22 @@ public class TvInteractiveAppView extends ViewGroup { } /** + * Alerts the TV Interactive app that the video freeze state has been updated. + * If {@code true}, the video is frozen on the last frame while audio playback continues. + * + * @param isFrozen Whether the video is frozen. + * @hide + */ + public void notifyVideoFreezeUpdated(boolean isFrozen) { + if (DEBUG) { + Log.d(TAG, "notifyVideoFreezeUpdated"); + } + if (mSession != null) { + mSession.notifyVideoFreezeUpdated(isFrozen); + } + } + + /** * Sends signing result to related TV interactive app. * * <p>This is used when the corresponding server of the broadcast-independent interactive diff --git a/media/tests/LoudnessCodecApiTest/src/com/android/loudnesscodecapitest/LoudnessCodecConfiguratorTest.java b/media/tests/LoudnessCodecApiTest/src/com/android/loudnesscodecapitest/LoudnessCodecControllerTest.java index 74e5612c0486..4f6ede508f7a 100644 --- a/media/tests/LoudnessCodecApiTest/src/com/android/loudnesscodecapitest/LoudnessCodecConfiguratorTest.java +++ b/media/tests/LoudnessCodecApiTest/src/com/android/loudnesscodecapitest/LoudnessCodecControllerTest.java @@ -24,19 +24,16 @@ import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.anyList; import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.content.Context; import android.content.res.AssetFileDescriptor; -import android.media.AudioAttributes; -import android.media.AudioFormat; -import android.media.AudioTrack; +import android.media.AudioManager; import android.media.IAudioService; -import android.media.LoudnessCodecConfigurator; -import android.media.LoudnessCodecConfigurator.OnLoudnessCodecUpdateListener; +import android.media.LoudnessCodecController; +import android.media.LoudnessCodecController.OnLoudnessCodecUpdateListener; import android.media.MediaCodec; import android.media.MediaExtractor; import android.media.MediaFormat; @@ -54,21 +51,19 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; -import java.util.List; import java.util.concurrent.Executors; /** - * Unit tests for {@link LoudnessCodecConfigurator} checking the internal interactions with a mocked + * Unit tests for {@link LoudnessCodecController} checking the internal interactions with a mocked * {@link IAudioService} without any real IPC interactions. */ @Presubmit @RunWith(AndroidJUnit4.class) -public class LoudnessCodecConfiguratorTest { +public class LoudnessCodecControllerTest { private static final String TAG = "LoudnessCodecConfiguratorTest"; private static final String TEST_MEDIA_AUDIO_CODEC_PREFIX = "audio/"; @@ -84,76 +79,41 @@ public class LoudnessCodecConfiguratorTest { @Mock private IAudioService mAudioService; - private LoudnessCodecConfigurator mLcc; + private LoudnessCodecController mLcc; + + private int mSessionId; @Before public void setUp() { - mLcc = LoudnessCodecConfigurator.createForTesting(mAudioService, - Executors.newSingleThreadExecutor(), new OnLoudnessCodecUpdateListener() {}); - } - - @Test - @RequiresFlagsEnabled(FLAG_LOUDNESS_CONFIGURATOR_API) - public void setAudioTrack_callsAudioServiceStart() throws Exception { - final AudioTrack track = createAudioTrack(); - final MediaCodec mediaCodec = createAndConfigureMediaCodec(); - - try { - mLcc.addMediaCodec(mediaCodec); - mLcc.setAudioTrack(track); - - verify(mAudioService).startLoudnessCodecUpdates(eq(track.getPlayerIId()), - anyList()); - } finally { - mediaCodec.release(); + final Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); + final AudioManager audioManager = (AudioManager) context.getSystemService( + AudioManager.class); + mSessionId = 0; + if (audioManager != null) { + mSessionId = audioManager.generateAudioSessionId(); } + mLcc = LoudnessCodecController.createForTesting(mSessionId, + Executors.newSingleThreadExecutor(), new OnLoudnessCodecUpdateListener() { + }, mAudioService); } @Test @RequiresFlagsEnabled(FLAG_LOUDNESS_CONFIGURATOR_API) - public void getLoudnessCodecParams_callsAudioServiceGetLoudness() throws Exception { - when(mAudioService.getLoudnessParams(anyInt(), any())).thenReturn(new PersistableBundle()); - final AudioTrack track = createAudioTrack(); - final MediaCodec mediaCodec = createAndConfigureMediaCodec(); - - try { - mLcc.getLoudnessCodecParams(track, mediaCodec); - - verify(mAudioService).getLoudnessParams(eq(track.getPlayerIId()), any()); - } finally { - mediaCodec.release(); - } + public void createLcc_callsAudioServiceStart() throws Exception { + verify(mAudioService).startLoudnessCodecUpdates(eq(mSessionId)); } @Test @RequiresFlagsEnabled(FLAG_LOUDNESS_CONFIGURATOR_API) - public void setAudioTrack_addsAudioServicePiidCodecs() throws Exception { - final AudioTrack track = createAudioTrack(); - final MediaCodec mediaCodec = createAndConfigureMediaCodec(); - - try { - mLcc.addMediaCodec(mediaCodec); - mLcc.setAudioTrack(track); - - verify(mAudioService).startLoudnessCodecUpdates(eq(track.getPlayerIId()), anyList()); - } finally { - mediaCodec.release(); - } - } - - @Test - @RequiresFlagsEnabled(FLAG_LOUDNESS_CONFIGURATOR_API) - public void setAudioTrackTwice_ignoresSecondCall() throws Exception { - final AudioTrack track = createAudioTrack(); + public void getLoudnessCodecParams_callsAudioServiceGetLoudness() throws Exception { + when(mAudioService.getLoudnessParams(any())).thenReturn(new PersistableBundle()); final MediaCodec mediaCodec = createAndConfigureMediaCodec(); try { mLcc.addMediaCodec(mediaCodec); - mLcc.setAudioTrack(track); - mLcc.setAudioTrack(track); + mLcc.getLoudnessCodecParams(mediaCodec); - verify(mAudioService, times(1)).startLoudnessCodecUpdates(eq(track.getPlayerIId()), - anyList()); + verify(mAudioService).getLoudnessParams(any()); } finally { mediaCodec.release(); } @@ -161,16 +121,14 @@ public class LoudnessCodecConfiguratorTest { @Test @RequiresFlagsEnabled(FLAG_LOUDNESS_CONFIGURATOR_API) - public void setTrackNull_stopCodecUpdates() throws Exception { - final AudioTrack track = createAudioTrack(); + public void release_stopCodecUpdates() throws Exception { final MediaCodec mediaCodec = createAndConfigureMediaCodec(); try { mLcc.addMediaCodec(mediaCodec); - mLcc.setAudioTrack(track); + mLcc.release(); // stops updats - mLcc.setAudioTrack(null); // stops updates - verify(mAudioService).stopLoudnessCodecUpdates(eq(track.getPlayerIId())); + verify(mAudioService).stopLoudnessCodecUpdates(eq(mSessionId)); } finally { mediaCodec.release(); } @@ -204,40 +162,14 @@ public class LoudnessCodecConfiguratorTest { @Test @RequiresFlagsEnabled(FLAG_LOUDNESS_CONFIGURATOR_API) - public void setClearTrack_removeAllAudioServicePiidCodecs() throws Exception { - final ArgumentCaptor<List> argument = ArgumentCaptor.forClass(List.class); - final AudioTrack track = createAudioTrack(); - final MediaCodec mediaCodec1 = createAndConfigureMediaCodec(); - final MediaCodec mediaCodec2 = createAndConfigureMediaCodec(); - - try { - mLcc.addMediaCodec(mediaCodec1); - mLcc.setAudioTrack(track); - verify(mAudioService).startLoudnessCodecUpdates(eq(track.getPlayerIId()), - argument.capture()); - assertEquals(argument.getValue().size(), 1); - - mLcc.addMediaCodec(mediaCodec2); - mLcc.setAudioTrack(null); - verify(mAudioService).stopLoudnessCodecUpdates(eq(track.getPlayerIId())); - } finally { - mediaCodec1.release(); - mediaCodec2.release(); - } - } - - @Test - @RequiresFlagsEnabled(FLAG_LOUDNESS_CONFIGURATOR_API) public void removeAddedMediaCodecAfterSetTrack_callsAudioServiceRemoveCodec() throws Exception { - final AudioTrack track = createAudioTrack(); final MediaCodec mediaCodec = createAndConfigureMediaCodec(); try { mLcc.addMediaCodec(mediaCodec); - mLcc.setAudioTrack(track); mLcc.removeMediaCodec(mediaCodec); - verify(mAudioService).removeLoudnessCodecInfo(eq(track.getPlayerIId()), any()); + verify(mAudioService).removeLoudnessCodecInfo(eq(mSessionId), any()); } finally { mediaCodec.release(); } @@ -245,37 +177,28 @@ public class LoudnessCodecConfiguratorTest { @Test @RequiresFlagsEnabled(FLAG_LOUDNESS_CONFIGURATOR_API) - public void addMediaCodecAfterSetTrack_callsAudioServiceAdd() throws Exception { - final AudioTrack track = createAudioTrack(); - final MediaCodec mediaCodec1 = createAndConfigureMediaCodec(); - final MediaCodec mediaCodec2 = createAndConfigureMediaCodec(); + public void addMediaCodec_callsAudioServiceAdd() throws Exception { + final MediaCodec mediaCodec = createAndConfigureMediaCodec(); try { - mLcc.addMediaCodec(mediaCodec1); - mLcc.setAudioTrack(track); - verify(mAudioService).startLoudnessCodecUpdates(eq(track.getPlayerIId()), anyList()); - - mLcc.addMediaCodec(mediaCodec2); - verify(mAudioService).addLoudnessCodecInfo(eq(track.getPlayerIId()), anyInt(), any()); + mLcc.addMediaCodec(mediaCodec); + verify(mAudioService).addLoudnessCodecInfo(eq(mSessionId), anyInt(), any()); } finally { - mediaCodec1.release(); - mediaCodec2.release(); + mediaCodec.release(); } } @Test @RequiresFlagsEnabled(FLAG_LOUDNESS_CONFIGURATOR_API) - public void removeMediaCodecAfterSetTrack_callsAudioServiceRemove() throws Exception { - final AudioTrack track = createAudioTrack(); + public void removeMediaCodec_callsAudioServiceRemove() throws Exception { final MediaCodec mediaCodec = createAndConfigureMediaCodec(); try { mLcc.addMediaCodec(mediaCodec); - mLcc.setAudioTrack(track); - verify(mAudioService).startLoudnessCodecUpdates(eq(track.getPlayerIId()), anyList()); + verify(mAudioService).addLoudnessCodecInfo(eq(mSessionId), anyInt(), any()); mLcc.removeMediaCodec(mediaCodec); - verify(mAudioService).removeLoudnessCodecInfo(eq(track.getPlayerIId()), any()); + verify(mAudioService).removeLoudnessCodecInfo(eq(mSessionId), any()); } finally { mediaCodec.release(); } @@ -283,15 +206,13 @@ public class LoudnessCodecConfiguratorTest { @Test @RequiresFlagsEnabled(FLAG_LOUDNESS_CONFIGURATOR_API) - public void removeWrongMediaCodecAfterSetTrack_triggersIAE() throws Exception { - final AudioTrack track = createAudioTrack(); + public void removeWrongMediaCodec_triggersIAE() throws Exception { final MediaCodec mediaCodec1 = createAndConfigureMediaCodec(); final MediaCodec mediaCodec2 = createAndConfigureMediaCodec(); try { mLcc.addMediaCodec(mediaCodec1); - mLcc.setAudioTrack(track); - verify(mAudioService).startLoudnessCodecUpdates(eq(track.getPlayerIId()), anyList()); + verify(mAudioService).addLoudnessCodecInfo(eq(mSessionId), anyInt(), any()); assertThrows(IllegalArgumentException.class, () -> mLcc.removeMediaCodec(mediaCodec2)); @@ -301,16 +222,6 @@ public class LoudnessCodecConfiguratorTest { } } - private static AudioTrack createAudioTrack() { - return new AudioTrack.Builder() - .setAudioAttributes(new AudioAttributes.Builder().build()) - .setBufferSizeInBytes(TEST_AUDIO_TRACK_BUFFER_SIZE) - .setAudioFormat(new AudioFormat.Builder() - .setChannelMask(TEST_AUDIO_TRACK_CHANNELS) - .setSampleRate(TEST_AUDIO_TRACK_SAMPLERATE).build()) - .build(); - } - private MediaCodec createAndConfigureMediaCodec() throws Exception { AssetFileDescriptor testFd = InstrumentationRegistry.getInstrumentation().getContext() .getResources() @@ -320,7 +231,7 @@ public class LoudnessCodecConfiguratorTest { extractor = new MediaExtractor(); try { extractor.setDataSource(testFd.getFileDescriptor(), testFd.getStartOffset(), - testFd.getLength()); + testFd.getLength()); assertEquals("wrong number of tracks", 1, extractor.getTrackCount()); MediaFormat format = extractor.getTrackFormat(0); String mime = format.getString(MediaFormat.KEY_MIME); diff --git a/native/android/performance_hint.cpp b/native/android/performance_hint.cpp index abe4a3d18b38..c5729444507e 100644 --- a/native/android/performance_hint.cpp +++ b/native/android/performance_hint.cpp @@ -228,11 +228,6 @@ int APerformanceHintSession::updateTargetWorkDuration(int64_t targetDurationNano } int APerformanceHintSession::reportActualWorkDuration(int64_t actualDurationNanos) { - if (actualDurationNanos <= 0) { - ALOGE("%s: actualDurationNanos must be positive", __FUNCTION__); - return EINVAL; - } - WorkDuration workDuration(0, actualDurationNanos, actualDurationNanos, 0); return reportActualWorkDurationInternal(&workDuration); @@ -320,23 +315,6 @@ int APerformanceHintSession::setPreferPowerEfficiency(bool enabled) { int APerformanceHintSession::reportActualWorkDuration(AWorkDuration* aWorkDuration) { WorkDuration* workDuration = static_cast<WorkDuration*>(aWorkDuration); - if (workDuration->workPeriodStartTimestampNanos <= 0) { - ALOGE("%s: workPeriodStartTimestampNanos must be positive", __FUNCTION__); - return EINVAL; - } - if (workDuration->actualTotalDurationNanos <= 0) { - ALOGE("%s: actualDurationNanos must be positive", __FUNCTION__); - return EINVAL; - } - if (workDuration->actualCpuDurationNanos <= 0) { - ALOGE("%s: cpuDurationNanos must be positive", __FUNCTION__); - return EINVAL; - } - if (workDuration->actualGpuDurationNanos < 0) { - ALOGE("%s: gpuDurationNanos must be non negative", __FUNCTION__); - return EINVAL; - } - return reportActualWorkDurationInternal(workDuration); } @@ -428,62 +406,87 @@ APerformanceHintManager* APerformanceHint_getManager() { return APerformanceHintManager::getInstance(); } +#define VALIDATE_PTR(ptr) \ + LOG_ALWAYS_FATAL_IF(ptr == nullptr, "%s: " #ptr " is nullptr", __FUNCTION__); + +#define VALIDATE_INT(value, cmp) \ + if (!(value cmp)) { \ + ALOGE("%s: Invalid value. Check failed: (" #value " " #cmp ") with value: %" PRIi64, \ + __FUNCTION__, value); \ + return EINVAL; \ + } + +#define WARN_INT(value, cmp) \ + if (!(value cmp)) { \ + ALOGE("%s: Invalid value. Check failed: (" #value " " #cmp ") with value: %" PRIi64, \ + __FUNCTION__, value); \ + } + APerformanceHintSession* APerformanceHint_createSession(APerformanceHintManager* manager, const int32_t* threadIds, size_t size, int64_t initialTargetWorkDurationNanos) { + VALIDATE_PTR(manager) + VALIDATE_PTR(threadIds) return manager->createSession(threadIds, size, initialTargetWorkDurationNanos); } int64_t APerformanceHint_getPreferredUpdateRateNanos(APerformanceHintManager* manager) { + VALIDATE_PTR(manager) return manager->getPreferredRateNanos(); } int APerformanceHint_updateTargetWorkDuration(APerformanceHintSession* session, int64_t targetDurationNanos) { + VALIDATE_PTR(session) return session->updateTargetWorkDuration(targetDurationNanos); } int APerformanceHint_reportActualWorkDuration(APerformanceHintSession* session, int64_t actualDurationNanos) { + VALIDATE_PTR(session) + VALIDATE_INT(actualDurationNanos, > 0) return session->reportActualWorkDuration(actualDurationNanos); } void APerformanceHint_closeSession(APerformanceHintSession* session) { + VALIDATE_PTR(session) delete session; } int APerformanceHint_sendHint(void* session, SessionHint hint) { + VALIDATE_PTR(session) return reinterpret_cast<APerformanceHintSession*>(session)->sendHint(hint); } int APerformanceHint_setThreads(APerformanceHintSession* session, const pid_t* threadIds, size_t size) { - if (session == nullptr) { - return EINVAL; - } + VALIDATE_PTR(session) + VALIDATE_PTR(threadIds) return session->setThreads(threadIds, size); } int APerformanceHint_getThreadIds(void* aPerformanceHintSession, int32_t* const threadIds, size_t* const size) { - if (aPerformanceHintSession == nullptr) { - return EINVAL; - } + VALIDATE_PTR(aPerformanceHintSession) return static_cast<APerformanceHintSession*>(aPerformanceHintSession) ->getThreadIds(threadIds, size); } int APerformanceHint_setPreferPowerEfficiency(APerformanceHintSession* session, bool enabled) { + VALIDATE_PTR(session) return session->setPreferPowerEfficiency(enabled); } int APerformanceHint_reportActualWorkDuration2(APerformanceHintSession* session, - AWorkDuration* workDuration) { - if (session == nullptr || workDuration == nullptr) { - ALOGE("Invalid value: (session %p, workDuration %p)", session, workDuration); - return EINVAL; - } - return session->reportActualWorkDuration(workDuration); + AWorkDuration* workDurationPtr) { + VALIDATE_PTR(session) + VALIDATE_PTR(workDurationPtr) + WorkDuration& workDuration = *static_cast<WorkDuration*>(workDurationPtr); + VALIDATE_INT(workDuration.workPeriodStartTimestampNanos, > 0) + VALIDATE_INT(workDuration.actualTotalDurationNanos, > 0) + VALIDATE_INT(workDuration.actualCpuDurationNanos, > 0) + VALIDATE_INT(workDuration.actualGpuDurationNanos, >= 0) + return session->reportActualWorkDuration(workDurationPtr); } AWorkDuration* AWorkDuration_create() { @@ -492,46 +495,36 @@ AWorkDuration* AWorkDuration_create() { } void AWorkDuration_release(AWorkDuration* aWorkDuration) { - if (aWorkDuration == nullptr) { - ALOGE("%s: aWorkDuration is nullptr", __FUNCTION__); - } + VALIDATE_PTR(aWorkDuration) delete aWorkDuration; } void AWorkDuration_setWorkPeriodStartTimestampNanos(AWorkDuration* aWorkDuration, int64_t workPeriodStartTimestampNanos) { - if (aWorkDuration == nullptr || workPeriodStartTimestampNanos <= 0) { - ALOGE("%s: Invalid value. (AWorkDuration: %p, workPeriodStartTimestampNanos: %" PRIi64 ")", - __FUNCTION__, aWorkDuration, workPeriodStartTimestampNanos); - } + VALIDATE_PTR(aWorkDuration) + WARN_INT(workPeriodStartTimestampNanos, > 0) static_cast<WorkDuration*>(aWorkDuration)->workPeriodStartTimestampNanos = workPeriodStartTimestampNanos; } void AWorkDuration_setActualTotalDurationNanos(AWorkDuration* aWorkDuration, int64_t actualTotalDurationNanos) { - if (aWorkDuration == nullptr || actualTotalDurationNanos <= 0) { - ALOGE("%s: Invalid value. (AWorkDuration: %p, actualTotalDurationNanos: %" PRIi64 ")", - __FUNCTION__, aWorkDuration, actualTotalDurationNanos); - } + VALIDATE_PTR(aWorkDuration) + WARN_INT(actualTotalDurationNanos, > 0) static_cast<WorkDuration*>(aWorkDuration)->actualTotalDurationNanos = actualTotalDurationNanos; } void AWorkDuration_setActualCpuDurationNanos(AWorkDuration* aWorkDuration, int64_t actualCpuDurationNanos) { - if (aWorkDuration == nullptr || actualCpuDurationNanos <= 0) { - ALOGE("%s: Invalid value. (AWorkDuration: %p, actualCpuDurationNanos: %" PRIi64 ")", - __FUNCTION__, aWorkDuration, actualCpuDurationNanos); - } + VALIDATE_PTR(aWorkDuration) + WARN_INT(actualCpuDurationNanos, > 0) static_cast<WorkDuration*>(aWorkDuration)->actualCpuDurationNanos = actualCpuDurationNanos; } void AWorkDuration_setActualGpuDurationNanos(AWorkDuration* aWorkDuration, int64_t actualGpuDurationNanos) { - if (aWorkDuration == nullptr || actualGpuDurationNanos < 0) { - ALOGE("%s: Invalid value. (AWorkDuration: %p, actualGpuDurationNanos: %" PRIi64 ")", - __FUNCTION__, aWorkDuration, actualGpuDurationNanos); - } + VALIDATE_PTR(aWorkDuration) + WARN_INT(actualGpuDurationNanos, >= 0) static_cast<WorkDuration*>(aWorkDuration)->actualGpuDurationNanos = actualGpuDurationNanos; } diff --git a/nfc/api/current.txt b/nfc/api/current.txt index 7573474f65b4..1046d8e9aebb 100644 --- a/nfc/api/current.txt +++ b/nfc/api/current.txt @@ -72,7 +72,7 @@ package android.nfc { method public void enableReaderMode(android.app.Activity, android.nfc.NfcAdapter.ReaderCallback, int, android.os.Bundle); method public static android.nfc.NfcAdapter getDefaultAdapter(android.content.Context); method @Nullable public android.nfc.NfcAntennaInfo getNfcAntennaInfo(); - method @FlaggedApi("android.nfc.enable_nfc_charging") @Nullable public android.nfc.WlcLDeviceInfo getWlcLDeviceInfo(); + method @FlaggedApi("android.nfc.enable_nfc_charging") @Nullable public android.nfc.WlcListenerDeviceInfo getWlcListenerDeviceInfo(); method public boolean ignore(android.nfc.Tag, int, android.nfc.NfcAdapter.OnTagRemovedListener, android.os.Handler); method public boolean isEnabled(); method @FlaggedApi("android.nfc.nfc_observe_mode") public boolean isObserveModeSupported(); @@ -175,18 +175,18 @@ package android.nfc { ctor public TagLostException(String); } - @FlaggedApi("android.nfc.enable_nfc_charging") public final class WlcLDeviceInfo implements android.os.Parcelable { - ctor public WlcLDeviceInfo(double, double, double, int); + @FlaggedApi("android.nfc.enable_nfc_charging") public final class WlcListenerDeviceInfo implements android.os.Parcelable { + ctor public WlcListenerDeviceInfo(int, double, double, int); method public int describeContents(); - method public double getBatteryLevel(); - method public double getProductId(); + method @FloatRange(from=0.0, to=100.0) public double getBatteryLevel(); + method public int getProductId(); method public int getState(); method public double getTemperature(); method public void writeToParcel(@NonNull android.os.Parcel, int); - field public static final int CONNECTED_CHARGING = 2; // 0x2 - field public static final int CONNECTED_DISCHARGING = 3; // 0x3 - field @NonNull public static final android.os.Parcelable.Creator<android.nfc.WlcLDeviceInfo> CREATOR; - field public static final int DISCONNECTED = 1; // 0x1 + field @NonNull public static final android.os.Parcelable.Creator<android.nfc.WlcListenerDeviceInfo> CREATOR; + field public static final int STATE_CONNECTED_CHARGING = 2; // 0x2 + field public static final int STATE_CONNECTED_DISCHARGING = 3; // 0x3 + field public static final int STATE_DISCONNECTED = 1; // 0x1 } } diff --git a/nfc/api/system-current.txt b/nfc/api/system-current.txt index 40672a1adc15..3524f8cce04c 100644 --- a/nfc/api/system-current.txt +++ b/nfc/api/system-current.txt @@ -8,7 +8,6 @@ package android.nfc { method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean enable(); method @FlaggedApi("android.nfc.enable_nfc_reader_option") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean enableReaderOption(boolean); method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean enableSecureNfc(boolean); - method @FlaggedApi("android.nfc.enable_nfc_charging") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean enableWlc(boolean); method @FlaggedApi("android.nfc.enable_nfc_mainline") public int getAdapterState(); method @NonNull @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public java.util.Map<java.lang.String,java.lang.Boolean> getTagIntentAppPreferenceForUser(int); method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public boolean isControllerAlwaysOn(); @@ -20,6 +19,7 @@ package android.nfc { method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public boolean setControllerAlwaysOn(boolean); method @FlaggedApi("android.nfc.enable_nfc_mainline") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setReaderMode(boolean); method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public int setTagIntentAppPreferenceForUser(int, @NonNull String, boolean); + method @FlaggedApi("android.nfc.enable_nfc_charging") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean setWlcEnabled(boolean); method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public void unregisterControllerAlwaysOnListener(@NonNull android.nfc.NfcAdapter.ControllerAlwaysOnListener); method @FlaggedApi("android.nfc.enable_nfc_charging") public void unregisterWlcStateListener(@NonNull android.nfc.NfcAdapter.WlcStateListener); field @FlaggedApi("android.nfc.enable_nfc_mainline") public static final String ACTION_REQUIRE_UNLOCK_FOR_NFC = "android.nfc.action.REQUIRE_UNLOCK_FOR_NFC"; @@ -37,7 +37,7 @@ package android.nfc { } @FlaggedApi("android.nfc.enable_nfc_charging") public static interface NfcAdapter.WlcStateListener { - method public void onWlcStateChanged(@NonNull android.nfc.WlcLDeviceInfo); + method public void onWlcStateChanged(@NonNull android.nfc.WlcListenerDeviceInfo); } } @@ -45,7 +45,7 @@ package android.nfc { package android.nfc.cardemulation { public final class CardEmulation { - method @FlaggedApi("android.permission.flags.wallet_role_enabled") @Nullable @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) public android.nfc.cardemulation.ApduServiceInfo getPreferredPaymentService(); + method @FlaggedApi("android.permission.flags.wallet_role_enabled") @Nullable @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) public static android.content.ComponentName getPreferredPaymentService(@NonNull android.content.Context); method @FlaggedApi("android.nfc.enable_nfc_mainline") @NonNull public java.util.List<android.nfc.cardemulation.ApduServiceInfo> getServices(@NonNull String, int); } diff --git a/nfc/java/android/nfc/INfcAdapter.aidl b/nfc/java/android/nfc/INfcAdapter.aidl index bec62c5b1b82..63c3414acc36 100644 --- a/nfc/java/android/nfc/INfcAdapter.aidl +++ b/nfc/java/android/nfc/INfcAdapter.aidl @@ -32,8 +32,8 @@ import android.nfc.ITagRemovedCallback; import android.nfc.INfcDta; import android.nfc.INfcWlcStateListener; import android.nfc.NfcAntennaInfo; +import android.nfc.WlcListenerDeviceInfo; import android.os.Bundle; -import android.nfc.WlcLDeviceInfo; /** * @hide @@ -90,11 +90,11 @@ interface INfcAdapter boolean setObserveMode(boolean enabled); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)") - boolean enableWlc(boolean enable); + boolean setWlcEnabled(boolean enable); boolean isWlcEnabled(); void registerWlcStateListener(in INfcWlcStateListener listener); void unregisterWlcStateListener(in INfcWlcStateListener listener); - WlcLDeviceInfo getWlcLDeviceInfo(); + WlcListenerDeviceInfo getWlcListenerDeviceInfo(); void updateDiscoveryTechnology(IBinder b, int pollFlags, int listenFlags); diff --git a/nfc/java/android/nfc/INfcWlcStateListener.aidl b/nfc/java/android/nfc/INfcWlcStateListener.aidl index c2b7075bc6e4..584eb9a128b4 100644 --- a/nfc/java/android/nfc/INfcWlcStateListener.aidl +++ b/nfc/java/android/nfc/INfcWlcStateListener.aidl @@ -16,7 +16,7 @@ package android.nfc; -import android.nfc.WlcLDeviceInfo; +import android.nfc.WlcListenerDeviceInfo; /** * @hide */ @@ -24,7 +24,7 @@ oneway interface INfcWlcStateListener { /** * Called whenever NFC WLC state changes * - * @param wlcLDeviceInfo NFC wlc listener information + * @param wlcListenerDeviceInfo NFC wlc listener information */ - void onWlcStateChanged(in WlcLDeviceInfo wlcLDeviceInfo); + void onWlcStateChanged(in WlcListenerDeviceInfo wlcListenerDeviceInfo); } diff --git a/nfc/java/android/nfc/NfcAdapter.java b/nfc/java/android/nfc/NfcAdapter.java index 68c16e69f3af..11eb97b440bf 100644 --- a/nfc/java/android/nfc/NfcAdapter.java +++ b/nfc/java/android/nfc/NfcAdapter.java @@ -2820,13 +2820,12 @@ public final class NfcAdapter { @SystemApi @FlaggedApi(Flags.FLAG_ENABLE_NFC_CHARGING) @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) - public boolean enableWlc(boolean enable) { + public boolean setWlcEnabled(boolean enable) { if (!sHasNfcWlcFeature) { throw new UnsupportedOperationException(); } try { - return sService.enableWlc(enable); - + return sService.setWlcEnabled(enable); } catch (RemoteException e) { attemptDeadServiceRecovery(e); // Try one more time @@ -2835,7 +2834,7 @@ public final class NfcAdapter { return false; } try { - return sService.enableWlc(enable); + return sService.setWlcEnabled(enable); } catch (RemoteException ee) { Log.e(TAG, "Failed to recover NFC Service."); } @@ -2887,7 +2886,7 @@ public final class NfcAdapter { /** * Called on NFC WLC state changes */ - void onWlcStateChanged(@NonNull WlcLDeviceInfo wlcLDeviceInfo); + void onWlcStateChanged(@NonNull WlcListenerDeviceInfo wlcListenerDeviceInfo); } /** @@ -2945,12 +2944,12 @@ public final class NfcAdapter { */ @FlaggedApi(Flags.FLAG_ENABLE_NFC_CHARGING) @Nullable - public WlcLDeviceInfo getWlcLDeviceInfo() { + public WlcListenerDeviceInfo getWlcListenerDeviceInfo() { if (!sHasNfcWlcFeature) { throw new UnsupportedOperationException(); } try { - return sService.getWlcLDeviceInfo(); + return sService.getWlcListenerDeviceInfo(); } catch (RemoteException e) { attemptDeadServiceRecovery(e); // Try one more time @@ -2959,7 +2958,7 @@ public final class NfcAdapter { return null; } try { - return sService.getWlcLDeviceInfo(); + return sService.getWlcListenerDeviceInfo(); } catch (RemoteException ee) { Log.e(TAG, "Failed to recover NFC Service."); } diff --git a/nfc/java/android/nfc/NfcWlcStateListener.java b/nfc/java/android/nfc/NfcWlcStateListener.java index 8d793101f41f..890cb090f587 100644 --- a/nfc/java/android/nfc/NfcWlcStateListener.java +++ b/nfc/java/android/nfc/NfcWlcStateListener.java @@ -36,7 +36,7 @@ public class NfcWlcStateListener extends INfcWlcStateListener.Stub { private final Map<WlcStateListener, Executor> mListenerMap = new HashMap<>(); - private WlcLDeviceInfo mCurrentState = null; + private WlcListenerDeviceInfo mCurrentState = null; private boolean mIsRegistered = false; public NfcWlcStateListener(@NonNull INfcAdapter adapter) { @@ -98,8 +98,10 @@ public class NfcWlcStateListener extends INfcWlcStateListener.Stub { Executor executor = mListenerMap.get(listener); final long identity = Binder.clearCallingIdentity(); try { - executor.execute(() -> listener.onWlcStateChanged( - mCurrentState)); + if (Flags.enableNfcCharging()) { + executor.execute(() -> listener.onWlcStateChanged( + mCurrentState)); + } } finally { Binder.restoreCallingIdentity(identity); } @@ -107,9 +109,9 @@ public class NfcWlcStateListener extends INfcWlcStateListener.Stub { } @Override - public void onWlcStateChanged(@NonNull WlcLDeviceInfo wlcLDeviceInfo) { + public void onWlcStateChanged(@NonNull WlcListenerDeviceInfo wlcListenerDeviceInfo) { synchronized (this) { - mCurrentState = wlcLDeviceInfo; + mCurrentState = wlcListenerDeviceInfo; for (WlcStateListener cb : mListenerMap.keySet()) { sendCurrentState(cb); diff --git a/nfc/java/android/nfc/WlcLDeviceInfo.java b/nfc/java/android/nfc/WlcLDeviceInfo.java deleted file mode 100644 index 016431e90d8e..000000000000 --- a/nfc/java/android/nfc/WlcLDeviceInfo.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (C) 2023 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.nfc; - -import android.annotation.FlaggedApi; -import android.annotation.NonNull; -import android.os.Parcel; -import android.os.Parcelable; - -/** - * Contains information of the nfc wireless charging listener device information. - */ -@FlaggedApi(Flags.FLAG_ENABLE_NFC_CHARGING) -public final class WlcLDeviceInfo implements Parcelable { - public static final int DISCONNECTED = 1; - - public static final int CONNECTED_CHARGING = 2; - - public static final int CONNECTED_DISCHARGING = 3; - - private double mProductId; - private double mTemperature; - private double mBatteryLevel; - private int mState; - - public WlcLDeviceInfo(double productId, double temperature, double batteryLevel, int state) { - this.mProductId = productId; - this.mTemperature = temperature; - this.mBatteryLevel = batteryLevel; - this.mState = state; - } - - /** - * ProductId of the WLC listener device. - */ - public double getProductId() { - return mProductId; - } - - /** - * Temperature of the WLC listener device. - */ - public double getTemperature() { - return mTemperature; - } - - /** - * BatteryLevel of the WLC listener device. - */ - public double getBatteryLevel() { - return mBatteryLevel; - } - - /** - * State of the WLC listener device. - */ - public int getState() { - return mState; - } - - private WlcLDeviceInfo(Parcel in) { - this.mProductId = in.readDouble(); - this.mTemperature = in.readDouble(); - this.mBatteryLevel = in.readDouble(); - this.mState = in.readInt(); - } - - public static final @NonNull Parcelable.Creator<WlcLDeviceInfo> CREATOR = - new Parcelable.Creator<WlcLDeviceInfo>() { - @Override - public WlcLDeviceInfo createFromParcel(Parcel in) { - return new WlcLDeviceInfo(in); - } - - @Override - public WlcLDeviceInfo[] newArray(int size) { - return new WlcLDeviceInfo[size]; - } - }; - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(@NonNull Parcel dest, int flags) { - dest.writeDouble(mProductId); - dest.writeDouble(mTemperature); - dest.writeDouble(mBatteryLevel); - dest.writeDouble(mState); - } -} diff --git a/nfc/java/android/nfc/WlcLDeviceInfo.aidl b/nfc/java/android/nfc/WlcListenerDeviceInfo.aidl index 33143fe81162..7f2ca545007b 100644 --- a/nfc/java/android/nfc/WlcLDeviceInfo.aidl +++ b/nfc/java/android/nfc/WlcListenerDeviceInfo.aidl @@ -16,4 +16,4 @@ package android.nfc; -parcelable WlcLDeviceInfo; +parcelable WlcListenerDeviceInfo; diff --git a/nfc/java/android/nfc/WlcListenerDeviceInfo.java b/nfc/java/android/nfc/WlcListenerDeviceInfo.java new file mode 100644 index 000000000000..45315f812250 --- /dev/null +++ b/nfc/java/android/nfc/WlcListenerDeviceInfo.java @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.nfc; + +import android.annotation.FlaggedApi; +import android.annotation.FloatRange; +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.os.Parcel; +import android.os.Parcelable; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Contains information of the nfc wireless charging listener device information. + */ +@FlaggedApi(Flags.FLAG_ENABLE_NFC_CHARGING) +public final class WlcListenerDeviceInfo implements Parcelable { + /** + * Device is currently not connected with any WlcListenerDevice. + */ + public static final int STATE_DISCONNECTED = 1; + + /** + * Device is currently connected with a WlcListenerDevice and is charging it. + */ + public static final int STATE_CONNECTED_CHARGING = 2; + + /** + * Device is currently connected with a WlcListenerDevice without charging it. + */ + public static final int STATE_CONNECTED_DISCHARGING = 3; + + /** + * Possible states from {@link #getState}. + * @hide + */ + @IntDef(prefix = { "STATE_" }, value = { + STATE_DISCONNECTED, + STATE_CONNECTED_CHARGING, + STATE_CONNECTED_DISCHARGING + }) + @Retention(RetentionPolicy.SOURCE) + public @interface WlcListenerState{} + + private int mProductId; + private double mTemperature; + private double mBatteryLevel; + private int mState; + + /** + * Create a new object containing wlc listener information. + * + * @param productId code for the device vendor + * @param temperature current temperature + * @param batteryLevel current battery level + * @param state current state + */ + public WlcListenerDeviceInfo(int productId, double temperature, double batteryLevel, + @WlcListenerState int state) { + this.mProductId = productId; + this.mTemperature = temperature; + this.mBatteryLevel = batteryLevel; + this.mState = state; + } + + /** + * ProductId of the WLC listener device. + * @return integer that is converted from USI Stylus VendorID[11:0]. + */ + public int getProductId() { + return mProductId; + } + + /** + * Temperature of the WLC listener device. + * @return the value represents the temperature in °C. + */ + public double getTemperature() { + return mTemperature; + } + + /** + * BatteryLevel of the WLC listener device. + * @return battery level in percentage [0-100] + */ + public @FloatRange(from = 0.0, to = 100.0) double getBatteryLevel() { + return mBatteryLevel; + } + + /** + * State of the WLC listener device. + */ + public @WlcListenerState int getState() { + return mState; + } + + private WlcListenerDeviceInfo(Parcel in) { + this.mProductId = in.readInt(); + this.mTemperature = in.readDouble(); + this.mBatteryLevel = in.readDouble(); + this.mState = in.readInt(); + } + + public static final @NonNull Parcelable.Creator<WlcListenerDeviceInfo> CREATOR = + new Parcelable.Creator<WlcListenerDeviceInfo>() { + @Override + public WlcListenerDeviceInfo createFromParcel(Parcel in) { + return new WlcListenerDeviceInfo(in); + } + + @Override + public WlcListenerDeviceInfo[] newArray(int size) { + return new WlcListenerDeviceInfo[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeInt(mProductId); + dest.writeDouble(mTemperature); + dest.writeDouble(mBatteryLevel); + dest.writeInt(mState); + } +} diff --git a/nfc/java/android/nfc/cardemulation/CardEmulation.java b/nfc/java/android/nfc/cardemulation/CardEmulation.java index 0943392a68ad..9d38e4c5b297 100644 --- a/nfc/java/android/nfc/cardemulation/CardEmulation.java +++ b/nfc/java/android/nfc/cardemulation/CardEmulation.java @@ -16,6 +16,7 @@ package android.nfc.cardemulation; +import android.Manifest; import android.annotation.FlaggedApi; import android.annotation.NonNull; import android.annotation.Nullable; @@ -23,6 +24,7 @@ import android.annotation.RequiresPermission; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.annotation.SystemApi; +import android.annotation.UserHandleAware; import android.annotation.UserIdInt; import android.app.Activity; import android.content.ComponentName; @@ -1138,31 +1140,28 @@ public final class CardEmulation { } /** - * Returns the {@link Settings.Secure#NFC_PAYMENT_DEFAULT_COMPONENT} for the given user. + * Returns the value of {@link Settings.Secure#NFC_PAYMENT_DEFAULT_COMPONENT}. + * + * @param context A context + * @return A ComponentName for the setting value, or null. * * @hide */ @SystemApi + @UserHandleAware @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) + @SuppressWarnings("AndroidFrameworkClientSidePermissionCheck") @FlaggedApi(android.permission.flags.Flags.FLAG_WALLET_ROLE_ENABLED) @Nullable - public ApduServiceInfo getPreferredPaymentService() { - try { - return sService.getPreferredPaymentService(mContext.getUser().getIdentifier()); - } catch (RemoteException e) { - // Try one more time - recoverService(); - if (sService == null) { - Log.e(TAG, "Failed to recover CardEmulationService."); - return null; - } - try { - return sService.getPreferredPaymentService(mContext.getUser().getIdentifier()); - } catch (RemoteException ee) { - Log.e(TAG, "Failed to reach CardEmulationService."); - return null; - } + public static ComponentName getPreferredPaymentService(@NonNull Context context) { + context.checkCallingOrSelfPermission(Manifest.permission.NFC_PREFERRED_PAYMENT_INFO); + String defaultPaymentComponent = Settings.Secure.getString(context.getContentResolver(), + Constants.SETTINGS_SECURE_NFC_PAYMENT_DEFAULT_COMPONENT); + + if (defaultPaymentComponent == null) { + return null; } - } + return ComponentName.unflattenFromString(defaultPaymentComponent); + } } diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/editor/SettingsExposedDropdownMenuCheckBox.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/editor/SettingsExposedDropdownMenuCheckBox.kt index ba8e354fa0c6..b34c310cd30f 100644 --- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/editor/SettingsExposedDropdownMenuCheckBox.kt +++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/editor/SettingsExposedDropdownMenuCheckBox.kt @@ -54,16 +54,18 @@ fun SettingsExposedDropdownMenuCheckBox( selectedOptionsState: SnapshotStateList<Int>, emptyVal: String = "", enabled: Boolean, + errorMessage: String? = null, onSelectedOptionStateChange: () -> Unit, ) { var dropDownWidth by remember { mutableIntStateOf(0) } var expanded by remember { mutableStateOf(false) } + val allIndex = options.indexOf("*") ExposedDropdownMenuBox( expanded = expanded, onExpandedChange = { expanded = it }, modifier = Modifier .width(350.dp) - .padding(SettingsDimension.menuFieldPadding) + .padding(SettingsDimension.textFieldPadding) .onSizeChanged { dropDownWidth = it.width }, ) { OutlinedTextField( @@ -72,7 +74,8 @@ fun SettingsExposedDropdownMenuCheckBox( .menuAnchor() .fillMaxWidth(), value = if (selectedOptionsState.size == 0) emptyVal - else selectedOptionsState.joinToString { options[it] }, + else if (selectedOptionsState.contains(allIndex)) "*" + else selectedOptionsState.joinToString { options[it] }, onValueChange = {}, label = { Text(text = label) }, trailingIcon = { @@ -81,7 +84,13 @@ fun SettingsExposedDropdownMenuCheckBox( ) }, readOnly = true, - enabled = enabled + enabled = enabled, + isError = errorMessage != null, + supportingText = { + if (errorMessage != null) { + Text(text = errorMessage) + } + } ) if (options.isNotEmpty()) { ExposedDropdownMenu( @@ -98,9 +107,17 @@ fun SettingsExposedDropdownMenuCheckBox( .fillMaxWidth(), onClick = { if (selectedOptionsState.contains(index)) { - selectedOptionsState.remove( - index - ) + if (index == allIndex) + selectedOptionsState.clear() + else { + selectedOptionsState.remove( + index + ) + if (selectedOptionsState.contains(allIndex)) + selectedOptionsState.remove( + allIndex + ) + } } else { selectedOptionsState.add( index diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml index 9ae4d0cc13c2..e3a313cad0b8 100644 --- a/packages/SettingsLib/res/values-af/strings.xml +++ b/packages/SettingsLib/res/values-af/strings.xml @@ -154,6 +154,8 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Prenttoestel"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Oorfoon"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Randinvoertoestel"</string> + <!-- no translation found for bluetooth_talkback_hearing_aids (3983279945542595479) --> + <skip /> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wi-Fi af."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wi-Fi is ontkoppel."</string> @@ -455,6 +457,10 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Kleurregstelling kan nuttig wees wanneer jy die volgende wil doen:<br/> <ol> <li>&nbsp;Om kleure meer akkuraat te sien</li> <li>&nbsp;Om kleure te verwyder om jou te help fokus</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Geneutraliseer deur <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_on_hold_settings_home_page (7690464049464805856) --> + <skip /> + <!-- no translation found for power_incompatible_charging_settings_home_page (1261756225093962684) --> + <skip /> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Ongeveer <xliff:g id="TIME_REMAINING">%1$s</xliff:g> oor"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"Ongeveer <xliff:g id="TIME_REMAINING">%1$s</xliff:g> oor (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"Ongeveer <xliff:g id="TIME_REMAINING">%1$s</xliff:g> oor gegrond op jou gebruik"</string> @@ -483,9 +489,12 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Laai tans draadloos"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Laai tans"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"Laai nie"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Gekoppel, laai nie"</string> + <!-- no translation found for battery_info_status_not_charging (1103084691314264664) --> + <skip /> <string name="battery_info_status_full" msgid="1339002294876531312">"Gelaai"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Volgelaai"</string> + <!-- no translation found for battery_info_status_charging_on_hold (6364355145521694438) --> + <skip /> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Beheer deur administrateur"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Beheer deur Beperkte Instellings"</string> <string name="disabled" msgid="8017887509554714950">"Gedeaktiveer"</string> diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml index c2be887ea777..dbd1af532b4d 100644 --- a/packages/SettingsLib/res/values-am/strings.xml +++ b/packages/SettingsLib/res/values-am/strings.xml @@ -154,6 +154,7 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"ምስል መስራት"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"የጆሮ ማዳመጫ"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"የግቤት መለዋወጫ"</string> + <string name="bluetooth_talkback_hearing_aids" msgid="3983279945542595479">"መስሚያ አጋዥ መሣሪያዎች"</string> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"ብሉቱዝ"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wifi ጠፍቷል።"</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"የWifi ግንኙነት ተቋርጧል።"</string> @@ -455,6 +456,8 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"የሚከተሉትን ለማድረግ ሲፈልጉ የቀለም ማስተካከያ ጠቃሚ ሊሆን ይችላል፡-<br/> <ol> <li>&nbsp;ቀለሞችን ይበልጥ በትክክል ለመመልከት</li> <li>&nbsp;ትኩረት ለማድረግ እንዲያግዙዎ ቀለሞችን ለማስወገድ</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"በ<xliff:g id="TITLE">%1$s</xliff:g> ተሽሯል"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <string name="power_charging_on_hold_settings_home_page" msgid="7690464049464805856">"<xliff:g id="LEVEL">%1$s</xliff:g> - ባትሪን ለመጠበቅ ኃይል መሙላት በይቆይ ላይ"</string> + <string name="power_incompatible_charging_settings_home_page" msgid="1261756225093962684">"<xliff:g id="LEVEL">%1$s</xliff:g> - የኃይል መሙያ መለዋወጫዎችን በመፈተሽ ላይ"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> ገደማ ቀርቷል"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>) ገደማ ቀርቷል"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"በአጠቃቀምዎ መሠረት <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ገደማ ቀርቷል"</string> @@ -483,9 +486,10 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"በገመድ-አልባ ኃይል በመሙላት ላይ"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"ኃይል በመሙላት ላይ"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"ባትሪ እየሞላ አይደለም"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"ተገናኝቷል፣ ኃይል በመሙላት ላይ አይደለም"</string> + <string name="battery_info_status_not_charging" msgid="1103084691314264664">"ተገናኝቷል፣ ነገር ግን ኃይል እየሞላ አይደለም"</string> <string name="battery_info_status_full" msgid="1339002294876531312">"ባትሪ ሞልቷል"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"ሙሉ ለሙሉ ኃይል ተሞልቷል"</string> + <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"ኃይል መሙላት በይቆይ ላይ"</string> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"በአስተዳዳሪ ቁጥጥር የተደረገበት"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"በተገደበ ቅንብር ቁጥጥር የሚደረግበት"</string> <string name="disabled" msgid="8017887509554714950">"ቦዝኗል"</string> diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml index 6c31c7687a55..ff220fad5950 100644 --- a/packages/SettingsLib/res/values-ar/strings.xml +++ b/packages/SettingsLib/res/values-ar/strings.xml @@ -154,6 +154,8 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"تصوير"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"السمّاعة"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"جهاز إدخال ملحق"</string> + <!-- no translation found for bluetooth_talkback_hearing_aids (3983279945542595479) --> + <skip /> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"بلوتوث"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"تم إيقاف Wi-Fi."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"تم قطع اتصال Wi-Fi."</string> @@ -455,6 +457,10 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"يمكنك الاستفادة من ميزة \"تصحيح الألوان\" من أجل:<br/> <ol> <li>&nbsp;رؤية الألوان بدقة أكبر</li> <li>&nbsp;إزالة الألوان لمساعدتك على التركيز</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"تم الاستبدال بـ <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_on_hold_settings_home_page (7690464049464805856) --> + <skip /> + <!-- no translation found for power_incompatible_charging_settings_home_page (1261756225093962684) --> + <skip /> <string name="power_remaining_duration_only" msgid="8264199158671531431">"يتبقى <xliff:g id="TIME_REMAINING">%1$s</xliff:g> تقريبًا."</string> <string name="power_discharging_duration" msgid="1076561255466053220">"يتبقى <xliff:g id="TIME_REMAINING">%1$s</xliff:g> تقريبًا (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"يتبقى <xliff:g id="TIME_REMAINING">%1$s</xliff:g> تقريبًا، بناءً على استخدامك"</string> @@ -483,9 +489,12 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"جارٍ الشحن لاسلكيًا"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"جارٍ الشحن"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"لا يتم الشحن"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"الجهاز متصل بالشاحن، ولا يتم الشحن."</string> + <!-- no translation found for battery_info_status_not_charging (1103084691314264664) --> + <skip /> <string name="battery_info_status_full" msgid="1339002294876531312">"مشحونة"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"البطارية مشحونة بالكامل."</string> + <!-- no translation found for battery_info_status_charging_on_hold (6364355145521694438) --> + <skip /> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"إعدادات يتحكم فيها المشرف"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"يتحكّم فيه إعداد محظور"</string> <string name="disabled" msgid="8017887509554714950">"غير مفعّل"</string> diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml index 8b06f5d40aff..47dad1f81455 100644 --- a/packages/SettingsLib/res/values-as/strings.xml +++ b/packages/SettingsLib/res/values-as/strings.xml @@ -154,6 +154,7 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"ইমেজিং"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"হেডফ\'ন"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"ইনপুট সম্পৰ্কীয় বাহ্য় ডিভাইচ"</string> + <string name="bluetooth_talkback_hearing_aids" msgid="3983279945542595479">"শ্ৰৱণ যন্ত্ৰ"</string> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"ব্লুটুথ"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"ৱাই-ফাই অফ হৈ আছে।"</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"ৱাইফাই সংযোগ বিচ্ছিন্ন হৈ আছে।"</string> @@ -455,6 +456,8 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"আপুনি এই কামসমূহ কৰিবলৈ বিচাৰিলে ৰং শুধৰণিৰ সুবিধাটো সহায়ক হ’ব পাৰে:<br/> <ol> <li>&nbsp;ৰঙবোৰ অধিক সঠিককৈ দেখা পোৱা</li> <li>&nbsp;আপোনাক মনোযোগ দিয়াত সহায় কৰিবলৈ ৰং আঁতৰোৱা</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g>ৰ দ্বাৰা অগ্ৰাহ্য কৰা হৈছে"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <string name="power_charging_on_hold_settings_home_page" msgid="7690464049464805856">"<xliff:g id="LEVEL">%1$s</xliff:g> - বেটাৰী সুৰক্ষিত কৰিবলৈ চাৰ্জিং স্থগিত ৰখা হৈছে"</string> + <string name="power_incompatible_charging_settings_home_page" msgid="1261756225093962684">"<xliff:g id="LEVEL">%1$s</xliff:g> - চাৰ্জিঙৰ আনুষংগিক বস্তু পৰীক্ষা কৰি থকা হৈছে"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"প্রায় <xliff:g id="TIME_REMAINING">%1$s</xliff:g> বাকী আছে"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"প্রায় <xliff:g id="TIME_REMAINING">%1$s</xliff:g> বাকী আছে (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"আপোনাৰ ব্যৱহাৰৰ ওপৰত ভিত্তি কৰি প্ৰায় <xliff:g id="TIME_REMAINING">%1$s</xliff:g> বাকী আছে"</string> @@ -483,9 +486,10 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"বেতাঁৰৰ মাধ্যমেৰে চাৰ্জ হৈ আছে"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"চাৰ্জ কৰি থকা হৈছে"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"চাৰ্জ কৰা নাই"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"সংযোগ হৈ আছে, চাৰ্জ হৈ থকা নাই"</string> + <string name="battery_info_status_not_charging" msgid="1103084691314264664">"সংযোজিত হৈছে, কিন্তু চাৰ্জ হৈ থকা নাই"</string> <string name="battery_info_status_full" msgid="1339002294876531312">"চাৰ্জ হ’ল"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"সম্পূৰ্ণ চাৰ্জ হৈছে"</string> + <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"চাৰ্জিং স্থগিত ৰখা হৈছে"</string> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"এডমিনৰ দ্বাৰা নিয়ন্ত্ৰিত"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"প্ৰতিবন্ধিত ছেটিঙৰ দ্বাৰা নিয়ন্ত্ৰিত"</string> <string name="disabled" msgid="8017887509554714950">"নিষ্ক্ৰিয়"</string> diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml index a36ab27a8f12..63154fce12dc 100644 --- a/packages/SettingsLib/res/values-az/strings.xml +++ b/packages/SettingsLib/res/values-az/strings.xml @@ -154,6 +154,8 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Şəkilləndirmə"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Qulaqlıq"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Daxiletmə periferiki"</string> + <!-- no translation found for bluetooth_talkback_hearing_aids (3983279945542595479) --> + <skip /> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wifi sönülüdür."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wifi bağlantı kəsildi."</string> @@ -455,6 +457,10 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Rəng korreksiyası bunları etmək istədikdə faydalı ola bilər:<br/> <ol> <li>&nbsp;Rəngləri daha dəqiq görmək</li> <li>&nbsp;Fokuslanmaq üçün rəngləri ləğv etmək</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> tərəfindən qəbul edilmir"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_on_hold_settings_home_page (7690464049464805856) --> + <skip /> + <!-- no translation found for power_incompatible_charging_settings_home_page (1261756225093962684) --> + <skip /> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Təxminən <xliff:g id="TIME_REMAINING">%1$s</xliff:g> qalıb"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"Təxminən <xliff:g id="TIME_REMAINING">%1$s</xliff:g> qalıb (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"İstifadəyə əsasən təxminən <xliff:g id="TIME_REMAINING">%1$s</xliff:g> qalıb"</string> @@ -483,9 +489,12 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Simsiz şarj edilir"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Şarj edilir"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"Doldurulmur"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Qoşulub, şarj edilmir"</string> + <!-- no translation found for battery_info_status_not_charging (1103084691314264664) --> + <skip /> <string name="battery_info_status_full" msgid="1339002294876531312">"Şarj edilib"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Tam şarj edilib"</string> + <!-- no translation found for battery_info_status_charging_on_hold (6364355145521694438) --> + <skip /> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Admin tərəfindən nəzarət olunur"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Məhdudlaşdırılmış Ayar ilə nəzarət edilir"</string> <string name="disabled" msgid="8017887509554714950">"Deaktiv"</string> diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml index 83f7c0572887..14f3883ef5b5 100644 --- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml +++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml @@ -154,6 +154,8 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Obrada slika"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Slušalice"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Periferni uređaj za unos"</string> + <!-- no translation found for bluetooth_talkback_hearing_aids (3983279945542595479) --> + <skip /> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"WiFi je isključen."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"WiFi veza je prekinuta."</string> @@ -455,6 +457,10 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Korekcija boja može da bude korisna kada želite:<br/> <ol> <li>&nbsp;Preciznije da vidite boje</li> <li>&nbsp;Da uklonite boje kako biste se fokusirali</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Zamenjuje ga <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g>–<xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_on_hold_settings_home_page (7690464049464805856) --> + <skip /> + <!-- no translation found for power_incompatible_charging_settings_home_page (1261756225093962684) --> + <skip /> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Preostalo je oko <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"Preostalo je oko <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"Preostalo je oko <xliff:g id="TIME_REMAINING">%1$s</xliff:g> na osnovu korišćenja"</string> @@ -483,9 +489,12 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Bežično punjenje"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Punjenje"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"Ne puni se"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Povezano, ne puni se"</string> + <!-- no translation found for battery_info_status_not_charging (1103084691314264664) --> + <skip /> <string name="battery_info_status_full" msgid="1339002294876531312">"Napunjeno"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Napunjeno do kraja"</string> + <!-- no translation found for battery_info_status_charging_on_hold (6364355145521694438) --> + <skip /> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Kontroliše administrator"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Kontrolišu ograničena podešavanja"</string> <string name="disabled" msgid="8017887509554714950">"Onemogućeno"</string> diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml index 7e8cd8b7b97a..fe0e60c29301 100644 --- a/packages/SettingsLib/res/values-be/strings.xml +++ b/packages/SettingsLib/res/values-be/strings.xml @@ -154,6 +154,7 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Прылада апрацоўкі відарысаў"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Навушнікі"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Перыферыйная прылада ўводу"</string> + <string name="bluetooth_talkback_hearing_aids" msgid="3983279945542595479">"Слыхавыя апараты"</string> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wi-Fi выключаны."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wi-Fi адлучаны."</string> @@ -455,6 +456,8 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Карэкцыя колераў можа спатрэбіцца, калі вы захочаце:<br/> <ol> <li>&nbsp;бачыць колеры больш дакладна;</li> <li>&nbsp;выдаліць колеры, каб сканцэнтраваць увагу.</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Перавызначаны <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <string name="power_charging_on_hold_settings_home_page" msgid="7690464049464805856">"<xliff:g id="LEVEL">%1$s</xliff:g> – зарадка прыпынена, каб абараніць акумулятар"</string> + <string name="power_incompatible_charging_settings_home_page" msgid="1261756225093962684">"<xliff:g id="LEVEL">%1$s</xliff:g> – правяраецца зарадная прылада"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Зараду хопіць прыблізна на <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"Зараду (<xliff:g id="LEVEL">%2$s</xliff:g>) хопіць прыблізна на <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"Зараду пры такім выкарыстанні хопіць прыблізна на <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -483,9 +486,10 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Бесправадная зарадка"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Ідзе зарадка"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"Не зараджаецца"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Падключана, не зараджаецца"</string> + <string name="battery_info_status_not_charging" msgid="1103084691314264664">"Прылада падключана, але не зараджаецца"</string> <string name="battery_info_status_full" msgid="1339002294876531312">"Зараджаны"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Акумулятар поўнасцю зараджаны"</string> + <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Зарадка прыпынена"</string> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Кантралюецца адміністратарам"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Пад кіраваннем Абмежаванага наладжвання"</string> <string name="disabled" msgid="8017887509554714950">"Адключанае"</string> diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml index d279349df5e3..53ffe114f142 100644 --- a/packages/SettingsLib/res/values-bg/strings.xml +++ b/packages/SettingsLib/res/values-bg/strings.xml @@ -154,6 +154,8 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Изображения"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Слушалки"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Периферен вход"</string> + <!-- no translation found for bluetooth_talkback_hearing_aids (3983279945542595479) --> + <skip /> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wi-Fi е изключен."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Няма връзка с Wi-Fi."</string> @@ -455,6 +457,10 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Функцията за корекция на цветовете може да бъде полезна, когато искате:<br/> <ol> <li>&nbsp;да виждате по-точни цветове;</li> <li>&nbsp;да премахнете цветовете, за да се съсредоточите.</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Заменено от „<xliff:g id="TITLE">%1$s</xliff:g>“"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_on_hold_settings_home_page (7690464049464805856) --> + <skip /> + <!-- no translation found for power_incompatible_charging_settings_home_page (1261756225093962684) --> + <skip /> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Още около <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"Още около <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"Още около <xliff:g id="TIME_REMAINING">%1$s</xliff:g> въз основа на използването"</string> @@ -483,9 +489,12 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Зарежда се безжично"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Зареждане"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"Не се зарежда"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Свързано, не се зарежда"</string> + <!-- no translation found for battery_info_status_not_charging (1103084691314264664) --> + <skip /> <string name="battery_info_status_full" msgid="1339002294876531312">"Заредена"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Напълно заредено"</string> + <!-- no translation found for battery_info_status_charging_on_hold (6364355145521694438) --> + <skip /> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Контролира се от администратор"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Управлява се чрез ограничена настройка"</string> <string name="disabled" msgid="8017887509554714950">"Деактивирано"</string> diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml index 3ac3a3b03c70..4e57e5f8f68c 100644 --- a/packages/SettingsLib/res/values-bn/strings.xml +++ b/packages/SettingsLib/res/values-bn/strings.xml @@ -154,6 +154,7 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"ইমেজিং"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"হেডফোন"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"পেরিফেরাল ইনপুট"</string> + <string name="bluetooth_talkback_hearing_aids" msgid="3983279945542595479">"হিয়ারিং এড"</string> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"ব্লুটুথ"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"ওয়াই ফাই বন্ধ৷"</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"ওয়াই-ফাই ডিসকানেক্ট হয়েছে৷"</string> @@ -455,6 +456,8 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"\'রঙ সংশোধন করা\' ফিচারের সাহায্যে এইসব কাজে করা যেতে পারে:<br/> <ol> <li>&nbsp;আরও সঠিকভাবে রঙ দেখা</li> <li>&nbsp;ফোকাস করার জন্য রঙ সরানো</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> এর দ্বারা ওভাররাইড করা হয়েছে"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <string name="power_charging_on_hold_settings_home_page" msgid="7690464049464805856">"<xliff:g id="LEVEL">%1$s</xliff:g> - ব্যাটারিকে সুরক্ষিত রাখতে চার্জিং হোল্ড করা হয়েছে"</string> + <string name="power_incompatible_charging_settings_home_page" msgid="1261756225093962684">"<xliff:g id="LEVEL">%1$s</xliff:g> - চার্জিংয়ের সরঞ্জাম চেক করা হচ্ছে"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"আর আনুমানিক <xliff:g id="TIME_REMAINING">%1$s</xliff:g> চলবে"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"আর আনুমানিক <xliff:g id="TIME_REMAINING">%1$s</xliff:g> চলবে (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"ব্যবহারের উপর ভিত্তি করে আর আনুমানিক <xliff:g id="TIME_REMAINING">%1$s</xliff:g> চলবে"</string> @@ -483,9 +486,10 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"কেবল ছাড়া চার্জ হচ্ছে"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"চার্জ হচ্ছে"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"চার্জ হচ্ছে না"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"কানেক্ট করা থাকলেও চার্জ করা হচ্ছে না"</string> + <string name="battery_info_status_not_charging" msgid="1103084691314264664">"কানেক্ট করা আছে, কিন্তু চার্জ হচ্ছে না"</string> <string name="battery_info_status_full" msgid="1339002294876531312">"চার্জ হয়েছে"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"সম্পূর্ণ চার্জ আছে"</string> + <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"চার্জিং হোল্ডে আছে"</string> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"প্রশাসকের দ্বারা নিয়ন্ত্রিত"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"এটি বিধিনিষেধ সেটিং থেকে নিয়ন্ত্রণ করা হয়"</string> <string name="disabled" msgid="8017887509554714950">"অক্ষম হয়েছে"</string> diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml index f84ccb0b1955..006849e0fd0d 100644 --- a/packages/SettingsLib/res/values-bs/strings.xml +++ b/packages/SettingsLib/res/values-bs/strings.xml @@ -154,6 +154,7 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Snimanje"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Slušalice"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Ulazni periferni uređaj"</string> + <string name="bluetooth_talkback_hearing_aids" msgid="3983279945542595479">"Slušna pomagala"</string> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"WiFi je isključen."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"WiFi nije povezan."</string> @@ -455,6 +456,8 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Ispravka boja može biti korisna kada želite:<br/> <ol> <li>&nbsp;jasnije vidjeti boje</li> <li>&nbsp;ukloniti boje radi lakšeg fokusiranja</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Zamjenjuje <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <string name="power_charging_on_hold_settings_home_page" msgid="7690464049464805856">"<xliff:g id="LEVEL">%1$s</xliff:g> – punjenje je pauzirano radi zaštite baterije"</string> + <string name="power_incompatible_charging_settings_home_page" msgid="1261756225093962684">"<xliff:g id="LEVEL">%1$s</xliff:g> – provjera dodatka za punjenje"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Preostalo je još oko <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"Preostalo je još oko <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"Preostalo je još oko <xliff:g id="TIME_REMAINING">%1$s</xliff:g> na osnovu vaše potrošnje"</string> @@ -483,9 +486,10 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Bežično punjenje"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Punjenje"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"Ne puni se"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Povezano, ne puni se"</string> + <string name="battery_info_status_not_charging" msgid="1103084691314264664">"Povezano, ali se ne puni"</string> <string name="battery_info_status_full" msgid="1339002294876531312">"Napunjeno"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Potpuno napunjeno"</string> + <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Punjenje na čekanju"</string> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Pod kontrolom administratora"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Kontrolira ograničena postavka"</string> <string name="disabled" msgid="8017887509554714950">"Onemogućeno"</string> diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml index c205f748a91d..6e95b3b6ccaa 100644 --- a/packages/SettingsLib/res/values-ca/strings.xml +++ b/packages/SettingsLib/res/values-ca/strings.xml @@ -154,6 +154,8 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Imatges"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Auricular"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Perifèric d\'entrada"</string> + <!-- no translation found for bluetooth_talkback_hearing_aids (3983279945542595479) --> + <skip /> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wi-Fi desactivada."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wi-Fi desconnectada."</string> @@ -455,6 +457,10 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"La correcció de color pot ser útil si vols:<br/> <ol> <li>&nbsp;Veure els colors amb més precisió.</li> <li>&nbsp;Suprimir els colors per concentrar-te millor.</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"S\'ha substituït per <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g>: <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_on_hold_settings_home_page (7690464049464805856) --> + <skip /> + <!-- no translation found for power_incompatible_charging_settings_home_page (1261756225093962684) --> + <skip /> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Temps restant aproximat: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"Temps restant aproximat: <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"Temps restant aproximat segons l\'ús que en fas: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -483,9 +489,12 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Carregant sense fil"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"S\'està carregant"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"No s\'està carregant"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Connectat; no s\'està carregant"</string> + <!-- no translation found for battery_info_status_not_charging (1103084691314264664) --> + <skip /> <string name="battery_info_status_full" msgid="1339002294876531312">"Carregada"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Totalment carregada"</string> + <!-- no translation found for battery_info_status_charging_on_hold (6364355145521694438) --> + <skip /> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Controlat per l\'administrador"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Controlat per la configuració restringida"</string> <string name="disabled" msgid="8017887509554714950">"Desactivat"</string> diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml index 53b7c707636f..96ee652f8737 100644 --- a/packages/SettingsLib/res/values-cs/strings.xml +++ b/packages/SettingsLib/res/values-cs/strings.xml @@ -154,6 +154,8 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Zobrazovací zařízení"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Sluchátka"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Periferní vstupní zařízení"</string> + <!-- no translation found for bluetooth_talkback_hearing_aids (3983279945542595479) --> + <skip /> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Síť Wi-Fi je vypnuta."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Síť Wi-Fi je odpojena."</string> @@ -455,6 +457,10 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Korekce barev se může hodit, když chcete:<br/> <ol> <li>&nbsp;Vidět barvy přesněji.</li> <li>&nbsp;Odstranit barvy kvůli zlepšení soustředění.</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Přepsáno nastavením <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_on_hold_settings_home_page (7690464049464805856) --> + <skip /> + <!-- no translation found for power_incompatible_charging_settings_home_page (1261756225093962684) --> + <skip /> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Zbývá asi <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"Zbývá asi <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"Při vašem obvyklém využití zbývá asi <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -483,9 +489,12 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Bezdrátové nabíjení"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Nabíjení"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"Nenabíjí se"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Připojeno, nenabíjí se"</string> + <!-- no translation found for battery_info_status_not_charging (1103084691314264664) --> + <skip /> <string name="battery_info_status_full" msgid="1339002294876531312">"Nabito"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Plně nabito"</string> + <!-- no translation found for battery_info_status_charging_on_hold (6364355145521694438) --> + <skip /> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Spravováno administrátorem"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Spravováno omezeným nastavením"</string> <string name="disabled" msgid="8017887509554714950">"Deaktivováno"</string> diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml index 0d0f0c62c6f1..61d0315e6d95 100644 --- a/packages/SettingsLib/res/values-da/strings.xml +++ b/packages/SettingsLib/res/values-da/strings.xml @@ -154,6 +154,8 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Billede"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Hovedtelefoner"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Eksterne inputenheder"</string> + <!-- no translation found for bluetooth_talkback_hearing_aids (3983279945542595479) --> + <skip /> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wi-Fi er slået fra."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wi-Fi er afbrudt."</string> @@ -455,6 +457,10 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Farvekorrigering kan være en nyttig funktion, når du vil:<br/> <ol> <li>&nbsp;Se farver mere nøjagtigt</li> <li>&nbsp;Fjerne farver, så du nemmere kan fokusere</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Tilsidesat af <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_on_hold_settings_home_page (7690464049464805856) --> + <skip /> + <!-- no translation found for power_incompatible_charging_settings_home_page (1261756225093962684) --> + <skip /> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Ca. <xliff:g id="TIME_REMAINING">%1$s</xliff:g> tilbage"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"Ca. <xliff:g id="TIME_REMAINING">%1$s</xliff:g> tilbage (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"Ca. <xliff:g id="TIME_REMAINING">%1$s</xliff:g> tilbage, alt efter hvordan du bruger enheden"</string> @@ -483,9 +489,12 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Trådløs opladning"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Oplader"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"Oplader ikke"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Tilsluttet, oplader ikke"</string> + <!-- no translation found for battery_info_status_not_charging (1103084691314264664) --> + <skip /> <string name="battery_info_status_full" msgid="1339002294876531312">"Opladet"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Fuldt opladet"</string> + <!-- no translation found for battery_info_status_charging_on_hold (6364355145521694438) --> + <skip /> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Kontrolleret af administratoren"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Styres af en begrænset indstilling"</string> <string name="disabled" msgid="8017887509554714950">"Deaktiveret"</string> diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml index 7936478306eb..58713d651452 100644 --- a/packages/SettingsLib/res/values-de/strings.xml +++ b/packages/SettingsLib/res/values-de/strings.xml @@ -154,6 +154,7 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Bildverarbeitung"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Kopfhörer"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Eingabeperipherie"</string> + <string name="bluetooth_talkback_hearing_aids" msgid="3983279945542595479">"Hörgerät"</string> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"WLAN: aus"</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"WLAN getrennt"</string> @@ -455,6 +456,8 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Die Farbkorrektur kann nützlich sein, wenn du:<br/> <ol> <li>&nbsp;Farben noch genauer sehen möchtest</li> <li>&nbsp;bestimmte Farben entfernen möchtest, um dich besser zu konzentrieren</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Außer Kraft gesetzt von \"<xliff:g id="TITLE">%1$s</xliff:g>\""</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <string name="power_charging_on_hold_settings_home_page" msgid="7690464049464805856">"<xliff:g id="LEVEL">%1$s</xliff:g> – Ladevorgang zum Schutz des Akkus angehalten"</string> + <string name="power_incompatible_charging_settings_home_page" msgid="1261756225093962684">"<xliff:g id="LEVEL">%1$s</xliff:g> – Ladezubehör wird geprüft"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Noch etwa <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"Noch etwa <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"Bei deinem Nutzungsmuster hast du noch ca. <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -483,9 +486,10 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Kabelloses Laden"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Wird geladen"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"Wird nicht geladen"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Verbunden, wird nicht geladen"</string> + <string name="battery_info_status_not_charging" msgid="1103084691314264664">"Verbunden, wird aber nicht geladen"</string> <string name="battery_info_status_full" msgid="1339002294876531312">"Aufgeladen"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Vollständig geladen"</string> + <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Ladevorgang angehalten"</string> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Durch den Administrator verwaltet"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Gesteuert durch eingeschränkte Einstellung"</string> <string name="disabled" msgid="8017887509554714950">"Deaktiviert"</string> diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml index 65f1f775efcf..2e4e507ed903 100644 --- a/packages/SettingsLib/res/values-el/strings.xml +++ b/packages/SettingsLib/res/values-el/strings.xml @@ -154,6 +154,8 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Απεικόνιση"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Ακουστικά"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Περιφερειακό εισόδου"</string> + <!-- no translation found for bluetooth_talkback_hearing_aids (3983279945542595479) --> + <skip /> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wi-Fi ανενεργό."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Το Wi-Fi έχει αποσυνδεθεί."</string> @@ -455,6 +457,10 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Η διόρθωση χρωμάτων μπορεί να σας φανεί χρήσιμη όταν θέλετε:<br/> <ol> <li>&nbsp;Μεγαλύτερη ακρίβεια στην απεικόνιση χρωμάτων</li> <li>&nbsp;Να καταργήσετε χρώματα για να συγκεντρωθείτε</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Αντικαταστάθηκε από <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_on_hold_settings_home_page (7690464049464805856) --> + <skip /> + <!-- no translation found for power_incompatible_charging_settings_home_page (1261756225093962684) --> + <skip /> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Απομένει/ουν περίπου <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"Απομένει/ουν περίπου <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"Απομένει/ουν περίπου <xliff:g id="TIME_REMAINING">%1$s</xliff:g>, βάσει της χρήσης σας"</string> @@ -483,9 +489,12 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Ασύρματη φόρτιση"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Φόρτιση"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"Δεν φορτίζει"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Συνδεδεμένη, δεν φορτίζει"</string> + <!-- no translation found for battery_info_status_not_charging (1103084691314264664) --> + <skip /> <string name="battery_info_status_full" msgid="1339002294876531312">"Φορτισμένη"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Πλήρως φορτισμένο"</string> + <!-- no translation found for battery_info_status_charging_on_hold (6364355145521694438) --> + <skip /> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Ελέγχονται από το διαχειριστή"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Ελέγχεται από τη Ρύθμιση με περιορισμό"</string> <string name="disabled" msgid="8017887509554714950">"Απενεργοποιημένο"</string> diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml index a5f089a7b200..3c6e70e4d360 100644 --- a/packages/SettingsLib/res/values-en-rAU/strings.xml +++ b/packages/SettingsLib/res/values-en-rAU/strings.xml @@ -154,6 +154,8 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Imaging"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Headphone"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Input Peripheral"</string> + <!-- no translation found for bluetooth_talkback_hearing_aids (3983279945542595479) --> + <skip /> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wi-Fi off."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wi-Fi disconnected."</string> @@ -455,6 +457,10 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Colour correction can be helpful when you want to:<br/> <ol> <li>&nbsp;See colours more accurately</li> <li>&nbsp;Remove colours to help you focus</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Overridden by <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_on_hold_settings_home_page (7690464049464805856) --> + <skip /> + <!-- no translation found for power_incompatible_charging_settings_home_page (1261756225093962684) --> + <skip /> <string name="power_remaining_duration_only" msgid="8264199158671531431">"About <xliff:g id="TIME_REMAINING">%1$s</xliff:g> left"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"About <xliff:g id="TIME_REMAINING">%1$s</xliff:g> left (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"About <xliff:g id="TIME_REMAINING">%1$s</xliff:g> left based on your usage"</string> @@ -483,9 +489,12 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Charging wirelessly"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Charging"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"Not charging"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Connected, not charging"</string> + <!-- no translation found for battery_info_status_not_charging (1103084691314264664) --> + <skip /> <string name="battery_info_status_full" msgid="1339002294876531312">"Charged"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Fully charged"</string> + <!-- no translation found for battery_info_status_charging_on_hold (6364355145521694438) --> + <skip /> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Controlled by admin"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Controlled by restricted setting"</string> <string name="disabled" msgid="8017887509554714950">"Disabled"</string> diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml index 1c51ea553414..ad683172e507 100644 --- a/packages/SettingsLib/res/values-en-rCA/strings.xml +++ b/packages/SettingsLib/res/values-en-rCA/strings.xml @@ -154,6 +154,7 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Imaging"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Headphone"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Input Peripheral"</string> + <string name="bluetooth_talkback_hearing_aids" msgid="3983279945542595479">"Hearing Aids"</string> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wifi off."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wifi disconnected."</string> @@ -455,6 +456,8 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Color correction can be helpful when you want to:<br/> <ol> <li>&nbsp;See colors more accurately</li> <li>&nbsp;Remove colors to help you focus</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Overridden by <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <string name="power_charging_on_hold_settings_home_page" msgid="7690464049464805856">"<xliff:g id="LEVEL">%1$s</xliff:g> - Charging on hold to protect battery"</string> + <string name="power_incompatible_charging_settings_home_page" msgid="1261756225093962684">"<xliff:g id="LEVEL">%1$s</xliff:g> - Checking charging accessory"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"About <xliff:g id="TIME_REMAINING">%1$s</xliff:g> left"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"About <xliff:g id="TIME_REMAINING">%1$s</xliff:g> left (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"About <xliff:g id="TIME_REMAINING">%1$s</xliff:g> left based on your usage"</string> @@ -483,9 +486,10 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Charging wirelessly"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Charging"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"Not charging"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Connected, not charging"</string> + <string name="battery_info_status_not_charging" msgid="1103084691314264664">"Connected, but not charging"</string> <string name="battery_info_status_full" msgid="1339002294876531312">"Charged"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Fully Charged"</string> + <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Charging on hold"</string> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Controlled by admin"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Controlled by Restricted Setting"</string> <string name="disabled" msgid="8017887509554714950">"Disabled"</string> diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml index a5f089a7b200..3c6e70e4d360 100644 --- a/packages/SettingsLib/res/values-en-rGB/strings.xml +++ b/packages/SettingsLib/res/values-en-rGB/strings.xml @@ -154,6 +154,8 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Imaging"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Headphone"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Input Peripheral"</string> + <!-- no translation found for bluetooth_talkback_hearing_aids (3983279945542595479) --> + <skip /> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wi-Fi off."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wi-Fi disconnected."</string> @@ -455,6 +457,10 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Colour correction can be helpful when you want to:<br/> <ol> <li>&nbsp;See colours more accurately</li> <li>&nbsp;Remove colours to help you focus</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Overridden by <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_on_hold_settings_home_page (7690464049464805856) --> + <skip /> + <!-- no translation found for power_incompatible_charging_settings_home_page (1261756225093962684) --> + <skip /> <string name="power_remaining_duration_only" msgid="8264199158671531431">"About <xliff:g id="TIME_REMAINING">%1$s</xliff:g> left"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"About <xliff:g id="TIME_REMAINING">%1$s</xliff:g> left (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"About <xliff:g id="TIME_REMAINING">%1$s</xliff:g> left based on your usage"</string> @@ -483,9 +489,12 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Charging wirelessly"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Charging"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"Not charging"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Connected, not charging"</string> + <!-- no translation found for battery_info_status_not_charging (1103084691314264664) --> + <skip /> <string name="battery_info_status_full" msgid="1339002294876531312">"Charged"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Fully charged"</string> + <!-- no translation found for battery_info_status_charging_on_hold (6364355145521694438) --> + <skip /> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Controlled by admin"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Controlled by restricted setting"</string> <string name="disabled" msgid="8017887509554714950">"Disabled"</string> diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml index a5f089a7b200..3c6e70e4d360 100644 --- a/packages/SettingsLib/res/values-en-rIN/strings.xml +++ b/packages/SettingsLib/res/values-en-rIN/strings.xml @@ -154,6 +154,8 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Imaging"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Headphone"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Input Peripheral"</string> + <!-- no translation found for bluetooth_talkback_hearing_aids (3983279945542595479) --> + <skip /> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wi-Fi off."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wi-Fi disconnected."</string> @@ -455,6 +457,10 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Colour correction can be helpful when you want to:<br/> <ol> <li>&nbsp;See colours more accurately</li> <li>&nbsp;Remove colours to help you focus</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Overridden by <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_on_hold_settings_home_page (7690464049464805856) --> + <skip /> + <!-- no translation found for power_incompatible_charging_settings_home_page (1261756225093962684) --> + <skip /> <string name="power_remaining_duration_only" msgid="8264199158671531431">"About <xliff:g id="TIME_REMAINING">%1$s</xliff:g> left"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"About <xliff:g id="TIME_REMAINING">%1$s</xliff:g> left (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"About <xliff:g id="TIME_REMAINING">%1$s</xliff:g> left based on your usage"</string> @@ -483,9 +489,12 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Charging wirelessly"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Charging"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"Not charging"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Connected, not charging"</string> + <!-- no translation found for battery_info_status_not_charging (1103084691314264664) --> + <skip /> <string name="battery_info_status_full" msgid="1339002294876531312">"Charged"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Fully charged"</string> + <!-- no translation found for battery_info_status_charging_on_hold (6364355145521694438) --> + <skip /> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Controlled by admin"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Controlled by restricted setting"</string> <string name="disabled" msgid="8017887509554714950">"Disabled"</string> diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml index 2ff386c91851..98106bfe6ca6 100644 --- a/packages/SettingsLib/res/values-en-rXC/strings.xml +++ b/packages/SettingsLib/res/values-en-rXC/strings.xml @@ -154,6 +154,7 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Imaging"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Headphone"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Input Peripheral"</string> + <string name="bluetooth_talkback_hearing_aids" msgid="3983279945542595479">"Hearing Aids"</string> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wifi off."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wifi disconnected."</string> @@ -455,6 +456,8 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Color correction can be helpful when you want to:<br/> <ol> <li>&nbsp;See colors more accurately</li> <li>&nbsp;Remove colors to help you focus</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Overridden by <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <string name="power_charging_on_hold_settings_home_page" msgid="7690464049464805856">"<xliff:g id="LEVEL">%1$s</xliff:g> - Charging on hold to protect battery"</string> + <string name="power_incompatible_charging_settings_home_page" msgid="1261756225093962684">"<xliff:g id="LEVEL">%1$s</xliff:g> - Checking charging accessory"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"About <xliff:g id="TIME_REMAINING">%1$s</xliff:g> left"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"About <xliff:g id="TIME_REMAINING">%1$s</xliff:g> left (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"About <xliff:g id="TIME_REMAINING">%1$s</xliff:g> left based on your usage"</string> @@ -483,9 +486,10 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Charging wirelessly"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Charging"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"Not charging"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Connected, not charging"</string> + <string name="battery_info_status_not_charging" msgid="1103084691314264664">"Connected, but not charging"</string> <string name="battery_info_status_full" msgid="1339002294876531312">"Charged"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Fully Charged"</string> + <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Charging on hold"</string> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Controlled by admin"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Controlled by Restricted Setting"</string> <string name="disabled" msgid="8017887509554714950">"Disabled"</string> diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml index 780a45de74d1..19f8b215c841 100644 --- a/packages/SettingsLib/res/values-es-rUS/strings.xml +++ b/packages/SettingsLib/res/values-es-rUS/strings.xml @@ -154,6 +154,7 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Imágenes"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Auriculares"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Periférico de entrada"</string> + <string name="bluetooth_talkback_hearing_aids" msgid="3983279945542595479">"Audífonos"</string> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wi-Fi inhabilitado"</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wi-Fi desconectado"</string> @@ -455,6 +456,8 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"La corrección de colores puede ser útil cuando quieres hacer lo siguiente:<br/> <ol> <li>&nbsp;Ver los colores con mayor precisión</li> <li>&nbsp;Quitar colores para concentrarte</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Reemplazado por <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <string name="power_charging_on_hold_settings_home_page" msgid="7690464049464805856">"<xliff:g id="LEVEL">%1$s</xliff:g> - Se detuvo la carga para proteger la batería"</string> + <string name="power_incompatible_charging_settings_home_page" msgid="1261756225093962684">"<xliff:g id="LEVEL">%1$s</xliff:g> - Verificando el accesorio de carga"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Tiempo restante: aproximadamente <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"Tiempo restante: aproximadamente <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"Tiempo restante: aproximadamente <xliff:g id="TIME_REMAINING">%1$s</xliff:g> en función de tu uso"</string> @@ -483,9 +486,10 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Carga inalámbrica"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Cargando"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"No se está cargando."</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Conectado; no se está cargando"</string> + <string name="battery_info_status_not_charging" msgid="1103084691314264664">"Conectado, pero no se está cargando"</string> <string name="battery_info_status_full" msgid="1339002294876531312">"Cargada"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Carga completa"</string> + <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Se detuvo la carga"</string> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Controlada por el administrador"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Controlada por la configuración restringida"</string> <string name="disabled" msgid="8017887509554714950">"Inhabilitada"</string> diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml index c07e1fd5ec42..8334379a9fb2 100644 --- a/packages/SettingsLib/res/values-es/strings.xml +++ b/packages/SettingsLib/res/values-es/strings.xml @@ -154,6 +154,8 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Escáner"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Auriculares"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Periférico de entrada"</string> + <!-- no translation found for bluetooth_talkback_hearing_aids (3983279945542595479) --> + <skip /> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wi-Fi desactivado."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wi-Fi desconectado."</string> @@ -455,6 +457,10 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Corrección de color puede ser útil si quieres:<br/> <ol> <li>&nbsp;Ver los colores mejor</li> <li>&nbsp;Quitar los colores para concentrarte mejor</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Anulado por <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g>: <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_on_hold_settings_home_page (7690464049464805856) --> + <skip /> + <!-- no translation found for power_incompatible_charging_settings_home_page (1261756225093962684) --> + <skip /> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Tiempo restante aproximado: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"Tiempo restante aproximado: <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"Tiempo restante aproximado según tu uso: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -483,9 +489,12 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Carga inalámbrica"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Cargando"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"No se está cargando"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Conectado pero sin cargar"</string> + <!-- no translation found for battery_info_status_not_charging (1103084691314264664) --> + <skip /> <string name="battery_info_status_full" msgid="1339002294876531312">"Cargada"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Carga completa"</string> + <!-- no translation found for battery_info_status_charging_on_hold (6364355145521694438) --> + <skip /> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Controlada por el administrador"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Controlado por ajustes restringidos"</string> <string name="disabled" msgid="8017887509554714950">"Inhabilitada"</string> diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml index ddc16b02ed81..35fd2dae93d3 100644 --- a/packages/SettingsLib/res/values-et/strings.xml +++ b/packages/SettingsLib/res/values-et/strings.xml @@ -154,6 +154,8 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Pildindus"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Kõrvaklapid"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Sisestatud välisseade"</string> + <!-- no translation found for bluetooth_talkback_hearing_aids (3983279945542595479) --> + <skip /> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"WiFi on välja lülitatud."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"WiFi-ühendus on katkestatud."</string> @@ -455,6 +457,10 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Värvide korrigeerimisest võib abi olla, kui soovite:<br/> <ol> <li>&nbsp;värve täpsemalt näha;</li> <li>&nbsp;värve eemaldada, et paremini keskenduda.</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Alistas <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_on_hold_settings_home_page (7690464049464805856) --> + <skip /> + <!-- no translation found for power_incompatible_charging_settings_home_page (1261756225093962684) --> + <skip /> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Ligikaudu <xliff:g id="TIME_REMAINING">%1$s</xliff:g> jäänud"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"Ligikaudu <xliff:g id="TIME_REMAINING">%1$s</xliff:g> jäänud (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"Teie kasutuse põhjal on jäänud ligikaudu <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -483,9 +489,12 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Juhtmevaba laadimine"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Laadimine"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"Ei lae"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Ühendatud, ei laeta"</string> + <!-- no translation found for battery_info_status_not_charging (1103084691314264664) --> + <skip /> <string name="battery_info_status_full" msgid="1339002294876531312">"Laetud"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Täielikult laetud"</string> + <!-- no translation found for battery_info_status_charging_on_hold (6364355145521694438) --> + <skip /> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Juhib administraator"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Haldavad piiranguga seaded"</string> <string name="disabled" msgid="8017887509554714950">"Keelatud"</string> diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml index 5d2210c2defe..89ab3a48454d 100644 --- a/packages/SettingsLib/res/values-eu/strings.xml +++ b/packages/SettingsLib/res/values-eu/strings.xml @@ -154,6 +154,8 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Irudietarako gailua"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Entzungailua"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Idazteko gailua"</string> + <!-- no translation found for bluetooth_talkback_hearing_aids (3983279945542595479) --> + <skip /> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth bidezko gailua"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Desaktibatuta dago wifi-konexioa."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Deskonektatu egin da wifi-konexioa."</string> @@ -455,6 +457,10 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Baliteke koloreen zuzenketa lagungarria izatea hauek egin nahi dituzunean:<br/> <ol> <li>&nbsp;Koloreak zehaztasun handiagoz ikusi.</li> <li>&nbsp;Koloreak kendu, arreta gal ez dezazun.</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> hobespena gainjarri zaio"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_on_hold_settings_home_page (7690464049464805856) --> + <skip /> + <!-- no translation found for power_incompatible_charging_settings_home_page (1261756225093962684) --> + <skip /> <string name="power_remaining_duration_only" msgid="8264199158671531431">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> inguru gelditzen dira"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> inguru gelditzen dira (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"Erabilera kontuan izanda, <xliff:g id="TIME_REMAINING">%1$s</xliff:g> inguru gelditzen dira"</string> @@ -483,9 +489,12 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Hari gabe kargatzen"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Kargatzen"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"Ez da kargatzen ari"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Konektatuta dago, baina ez da kargatzen ari"</string> + <!-- no translation found for battery_info_status_not_charging (1103084691314264664) --> + <skip /> <string name="battery_info_status_full" msgid="1339002294876531312">"Kargatuta"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Erabat kargatuta"</string> + <!-- no translation found for battery_info_status_charging_on_hold (6364355145521694438) --> + <skip /> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Administratzaileak kontrolatzen du"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Ezarpen mugatuak kontrolatzen du"</string> <string name="disabled" msgid="8017887509554714950">"Desgaituta"</string> diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml index d73571e2f570..68d9ed156353 100644 --- a/packages/SettingsLib/res/values-fa/strings.xml +++ b/packages/SettingsLib/res/values-fa/strings.xml @@ -154,6 +154,7 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"تصویربرداری"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"هدفون"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"ورودی محیطی"</string> + <string name="bluetooth_talkback_hearing_aids" msgid="3983279945542595479">"سمعک"</string> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"بلوتوث"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wi‑Fi خاموش است."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wi-Fi قطع شد."</string> @@ -455,6 +456,8 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"«تصحیح رنگ» میتواند در مواقع زیر مفید باشد:<br/> <ol> <li>&nbsp;وقتی میخواهید رنگها را دقیقتر ببینید</li> <li>&nbsp;وقتی میخواهید رنگها را حذف کنید تا بتوانید راحتتر تمرکز کنید</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"توسط <xliff:g id="TITLE">%1$s</xliff:g> لغو شد"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <string name="power_charging_on_hold_settings_home_page" msgid="7690464049464805856">"<xliff:g id="LEVEL">%1$s</xliff:g> - برای محافظت از باتری، شارژ موقتاً متوقف شده است"</string> + <string name="power_incompatible_charging_settings_home_page" msgid="1261756225093962684">"<xliff:g id="LEVEL">%1$s</xliff:g> - بررسی لوازم شارژ"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"تقریباً <xliff:g id="TIME_REMAINING">%1$s</xliff:g> شارژ باقی مانده است"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"تقریباً <xliff:g id="TIME_REMAINING">%1$s</xliff:g> شارژ باقی مانده است (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"براساس مصرفتان، تقریباً <xliff:g id="TIME_REMAINING">%1$s</xliff:g> شارژ باقی مانده است"</string> @@ -483,9 +486,10 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"درحال شارژ بیسیم"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"درحال شارژ شدن"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"شارژ نمیشود"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"متصل، شارژ نمیشود"</string> + <string name="battery_info_status_not_charging" msgid="1103084691314264664">"متصل است، اما شارژ نمیشود"</string> <string name="battery_info_status_full" msgid="1339002294876531312">"شارژ کامل شد"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"کاملاً شارژ شده است"</string> + <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"شارژ موقتاً متوقف شده است"</string> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"توسط سرپرست سیستم کنترل میشود"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"با تنظیم «حالت محدود» کنترل میشود"</string> <string name="disabled" msgid="8017887509554714950">"غیر فعال شد"</string> diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml index 3533d77cb8db..13cface55fc7 100644 --- a/packages/SettingsLib/res/values-fi/strings.xml +++ b/packages/SettingsLib/res/values-fi/strings.xml @@ -154,6 +154,7 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Kuvannuslaite"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Kuulokkeet"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Syöttölisälaite"</string> + <string name="bluetooth_talkback_hearing_aids" msgid="3983279945542595479">"Kuulolaitteet"</string> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wi-Fi pois käytöstä"</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Ei Wi-Fi-yhteyttä"</string> @@ -455,6 +456,8 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Värinkorjaus voi auttaa seuraavissa:<br/> <ol> <li>&nbsp;Värien tarkempi näkeminen</li> <li>&nbsp;Värien poistaminen keskittymisen parantamiseksi</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Tämän ohittaa <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <string name="power_charging_on_hold_settings_home_page" msgid="7690464049464805856">"<xliff:g id="LEVEL">%1$s</xliff:g> – Lataus on keskeytetty akun suojaamiseksi"</string> + <string name="power_incompatible_charging_settings_home_page" msgid="1261756225093962684">"<xliff:g id="LEVEL">%1$s</xliff:g> – Tarkistetaan latauslisävarustetta"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Noin <xliff:g id="TIME_REMAINING">%1$s</xliff:g> jäljellä"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"Noin <xliff:g id="TIME_REMAINING">%1$s</xliff:g> jäljellä (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"Noin <xliff:g id="TIME_REMAINING">%1$s</xliff:g> jäljellä käyttösi perusteella"</string> @@ -483,9 +486,10 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Langaton lataus"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Ladataan"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"Ei laturissa"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Yhdistetty, ei ladata"</string> + <string name="battery_info_status_not_charging" msgid="1103084691314264664">"Yhdistetty, mutta ei latauksessa"</string> <string name="battery_info_status_full" msgid="1339002294876531312">"Ladattu"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Täyteen ladattu"</string> + <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Lataus on pidossa"</string> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Järjestelmänvalvoja hallinnoi tätä asetusta."</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Rajoitettujen asetusten mukaisesti"</string> <string name="disabled" msgid="8017887509554714950">"Pois päältä"</string> diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml index 06eeae03a46c..cb6d27be8703 100644 --- a/packages/SettingsLib/res/values-fr-rCA/strings.xml +++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml @@ -154,6 +154,8 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Imagerie"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Écouteurs"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Périphérique d\'entrée"</string> + <!-- no translation found for bluetooth_talkback_hearing_aids (3983279945542595479) --> + <skip /> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wi-Fi désactivé."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wi-Fi déconnecté."</string> @@ -180,7 +182,7 @@ <string name="launch_defaults_none" msgid="8049374306261262709">"Aucune préférence par défaut définie"</string> <string name="tts_settings" msgid="8130616705989351312">"Paramètres de synthèse vocale"</string> <string name="tts_settings_title" msgid="7602210956640483039">"Synthèse vocale"</string> - <string name="tts_default_rate_title" msgid="3964187817364304022">"Cadence"</string> + <string name="tts_default_rate_title" msgid="3964187817364304022">"Débit"</string> <string name="tts_default_rate_summary" msgid="3781937042151716987">"Vitesse à laquelle le texte est énoncé"</string> <string name="tts_default_pitch_title" msgid="6988592215554485479">"Ton"</string> <string name="tts_default_pitch_summary" msgid="9132719475281551884">"Touche le ton utilisé pour la synthèse vocale"</string> @@ -455,6 +457,10 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"La correction des couleurs peut être utile lorsque vous souhaitez :<br/> <ol> <li> voir les couleurs avec plus de précision;</li> <li> retirer les couleurs pour vous aider à vous concentrer.</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Remplacé par <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> : <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_on_hold_settings_home_page (7690464049464805856) --> + <skip /> + <!-- no translation found for power_incompatible_charging_settings_home_page (1261756225093962684) --> + <skip /> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Il reste environ <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"Il reste environ <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"Il reste environ <xliff:g id="TIME_REMAINING">%1$s</xliff:g> en fonction de votre usage"</string> @@ -483,9 +489,12 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"En recharge sans fil"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Recharge en cours…"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"N\'est pas en charge"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Connecté, pas en charge"</string> + <!-- no translation found for battery_info_status_not_charging (1103084691314264664) --> + <skip /> <string name="battery_info_status_full" msgid="1339002294876531312">"Chargée"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Complètement rechargée"</string> + <!-- no translation found for battery_info_status_charging_on_hold (6364355145521694438) --> + <skip /> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Contrôlé par l\'administrateur"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Contrôlé par les paramètres restreints"</string> <string name="disabled" msgid="8017887509554714950">"Désactivée"</string> diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml index e30a4ab3cf32..ae6d48e90bef 100644 --- a/packages/SettingsLib/res/values-fr/strings.xml +++ b/packages/SettingsLib/res/values-fr/strings.xml @@ -154,6 +154,7 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Imagerie"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Casque audio"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Périphérique d\'entrée"</string> + <string name="bluetooth_talkback_hearing_aids" msgid="3983279945542595479">"Appareils auditifs"</string> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wi-Fi désactivé"</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wi-Fi déconnecté"</string> @@ -455,6 +456,8 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"La correction des couleurs peut vous être utile pour :<br/> <ol> <li>&nbsp;Distinguer les couleurs plus précisément</li> <li>&nbsp;Supprimer les couleurs afin de mieux vous concentrer</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Remplacé par <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <string name="power_charging_on_hold_settings_home_page" msgid="7690464049464805856">"<xliff:g id="LEVEL">%1$s</xliff:g> - Recharge en pause pour protéger la batterie"</string> + <string name="power_incompatible_charging_settings_home_page" msgid="1261756225093962684">"<xliff:g id="LEVEL">%1$s</xliff:g> - Vérification de l\'accessoire de recharge"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Temps restant : environ <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"Temps restant : environ <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"Temps restant en fonction de votre utilisation : environ <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -483,9 +486,10 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"En charge sans fil"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Recharge"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"Pas en charge"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Connectée, pas en charge"</string> + <string name="battery_info_status_not_charging" msgid="1103084691314264664">"Connecté, mais pas en cours de recharge"</string> <string name="battery_info_status_full" msgid="1339002294876531312">"Chargée"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Complètement chargée"</string> + <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Recharge en pause"</string> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Contrôlé par l\'administrateur"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Contrôlé par les paramètres restreints"</string> <string name="disabled" msgid="8017887509554714950">"Désactivée"</string> diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml index f896d16c07f2..11d083884ba9 100644 --- a/packages/SettingsLib/res/values-gl/strings.xml +++ b/packages/SettingsLib/res/values-gl/strings.xml @@ -154,6 +154,8 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Dispositivo de imaxe"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Auriculares"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Periférico de entrada"</string> + <!-- no translation found for bluetooth_talkback_hearing_aids (3983279945542595479) --> + <skip /> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wifi desactivada."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wifi desconectada."</string> @@ -455,6 +457,10 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"A corrección da cor pode serche útil se queres:<br/> <ol> <li>&nbsp;Ver mellor as cores</li> <li>&nbsp;Quitar as cores para concentrarte mellor</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Anulado por <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_on_hold_settings_home_page (7690464049464805856) --> + <skip /> + <!-- no translation found for power_incompatible_charging_settings_home_page (1261756225093962684) --> + <skip /> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Tempo restante aproximado: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"Tempo restante aproximado (<xliff:g id="LEVEL">%2$s</xliff:g>): <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"Tempo restante aproximado en función do uso: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -483,9 +489,12 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Cargando sen fíos"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Cargando"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"Non se está cargando"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Conectado, sen cargar"</string> + <!-- no translation found for battery_info_status_not_charging (1103084691314264664) --> + <skip /> <string name="battery_info_status_full" msgid="1339002294876531312">"Cargada"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Carga completa"</string> + <!-- no translation found for battery_info_status_charging_on_hold (6364355145521694438) --> + <skip /> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Opción controlada polo administrador"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Baixo o control de opcións restrinxidas"</string> <string name="disabled" msgid="8017887509554714950">"Desactivada"</string> diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml index 50741ddb72da..ebd02c3b510c 100644 --- a/packages/SettingsLib/res/values-gu/strings.xml +++ b/packages/SettingsLib/res/values-gu/strings.xml @@ -154,6 +154,8 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"ઇમેજિંગ"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"હેડફોન"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"ઇનપુટ પેરિફેરલ"</string> + <!-- no translation found for bluetooth_talkback_hearing_aids (3983279945542595479) --> + <skip /> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"બ્લૂટૂથ"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wifi બંધ."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wifi ડિસ્કનેક્ટ થયું."</string> @@ -455,6 +457,10 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"રંગમાં સુધારણા કરવાની સુવિધાનો ઉપયોગ ત્યારે સહાયરૂપ બની શકે છે કે જ્યારે તમે આ કરવા માગતા હો:<br/> <ol> <li>&nbsp;વધુ સચોટપણે રંગ જોવા</li> <li>&nbsp;ફોકસ કરવામાં સહાય માટે અમુક રંગ કાઢી નાખવા</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> દ્વારા ઓવરરાઇડ થયું"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_on_hold_settings_home_page (7690464049464805856) --> + <skip /> + <!-- no translation found for power_incompatible_charging_settings_home_page (1261756225093962684) --> + <skip /> <string name="power_remaining_duration_only" msgid="8264199158671531431">"લગભગ <xliff:g id="TIME_REMAINING">%1$s</xliff:g> બાકી છે"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"લગભગ <xliff:g id="TIME_REMAINING">%1$s</xliff:g> બાકી છે (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"તમારા વપરાશના આધારે લગભગ <xliff:g id="TIME_REMAINING">%1$s</xliff:g> બાકી છે"</string> @@ -483,9 +489,12 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"વાયરલેસથી ચાર્જિંગ"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"ચાર્જ થઈ રહ્યું છે"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"ચાર્જ થઈ રહ્યું નથી"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"કનેક્ટ કરેલું છે, પણ ચાર્જ થઈ રહ્યું નથી"</string> + <!-- no translation found for battery_info_status_not_charging (1103084691314264664) --> + <skip /> <string name="battery_info_status_full" msgid="1339002294876531312">"ચાર્જ થયું"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"સંપૂર્ણપણે ચાર્જ છે"</string> + <!-- no translation found for battery_info_status_charging_on_hold (6364355145521694438) --> + <skip /> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"વ્યવસ્થાપક દ્વારા નિયંત્રિત"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"પ્રતિબંધિત સેટિંગ દ્વારા નિયંત્રિત"</string> <string name="disabled" msgid="8017887509554714950">"અક્ષમ કર્યો"</string> diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml index 0a29b6a06835..e03de1572c34 100644 --- a/packages/SettingsLib/res/values-hi/strings.xml +++ b/packages/SettingsLib/res/values-hi/strings.xml @@ -154,6 +154,8 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"इमेजिंग"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"हेडफ़ोन"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"इनपुट पेरिफ़ेरल"</string> + <!-- no translation found for bluetooth_talkback_hearing_aids (3983279945542595479) --> + <skip /> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"ब्लूटूथ"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"वाई-फ़ाई बंद है."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"वाई-फ़ाई डिसकनेक्ट है."</string> @@ -455,6 +457,10 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"रंग में सुधार करने की सुविधा का इस्तेमाल, इन मामलों में किया जा सकता है:<br/> <ol> <li>&nbsp;आपको ज़्यादा सटीक तरह से रंग देखने हों</li> <li>&nbsp;ज़्यादा फ़ोकस करने के लिए, आपको कुछ खास रंग हटाने हों</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> के द्वारा ओवरराइड किया गया"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_on_hold_settings_home_page (7690464049464805856) --> + <skip /> + <!-- no translation found for power_incompatible_charging_settings_home_page (1261756225093962684) --> + <skip /> <string name="power_remaining_duration_only" msgid="8264199158671531431">"बैटरी करीब <xliff:g id="TIME_REMAINING">%1$s</xliff:g> में खत्म हो जाएगी"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"बैटरी करीब <xliff:g id="TIME_REMAINING">%1$s</xliff:g> में खत्म हो जाएगी (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"आपके इस्तेमाल के हिसाब से बैटरी करीब <xliff:g id="TIME_REMAINING">%1$s</xliff:g> में खत्म हो जाएगी"</string> @@ -483,9 +489,12 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"वायरलेस चार्जिंग"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"चार्ज हो रहा है"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"चार्ज नहीं हो रही है"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"कनेक्ट किया गया, चार्ज नहीं हो रहा है"</string> + <!-- no translation found for battery_info_status_not_charging (1103084691314264664) --> + <skip /> <string name="battery_info_status_full" msgid="1339002294876531312">"बैटरी चार्ज हो गई"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"बैटरी पूरी चार्ज है"</string> + <!-- no translation found for battery_info_status_charging_on_hold (6364355145521694438) --> + <skip /> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"इसका नियंत्रण एडमिन के पास है"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"इसे पाबंदी मोड वाली सेटिंग से कंट्रोल किया जाता है"</string> <string name="disabled" msgid="8017887509554714950">"बंद किया गया"</string> diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml index b206ac0f59e6..259779ab9c9f 100644 --- a/packages/SettingsLib/res/values-hr/strings.xml +++ b/packages/SettingsLib/res/values-hr/strings.xml @@ -154,6 +154,7 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Snimanje"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Slušalice"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Periferni uređaj za unos"</string> + <string name="bluetooth_talkback_hearing_aids" msgid="3983279945542595479">"Slušna pomagala"</string> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wi-Fi je isključen."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wi-Fi je isključen."</string> @@ -455,6 +456,8 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Korekcija boja može biti korisna kad želite:<br/> <ol> <li>&nbsp;preciznije vidjeti boje</li> <li>&nbsp;ukloniti boje kako biste se lakše usredotočili.</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Premošćeno postavkom <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <string name="power_charging_on_hold_settings_home_page" msgid="7690464049464805856">"<xliff:g id="LEVEL">%1$s</xliff:g> – punjenje je pauzirano radi zaštite baterije"</string> + <string name="power_incompatible_charging_settings_home_page" msgid="1261756225093962684">"<xliff:g id="LEVEL">%1$s</xliff:g> – provjera dodatka za punjenje"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Još oko <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"Još otprilike <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"Još otprilike <xliff:g id="TIME_REMAINING">%1$s</xliff:g> na temelju vaše upotrebe"</string> @@ -483,9 +486,10 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Bežično punjenje"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Punjenje"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"Ne puni se"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Povezano, ne puni se"</string> + <string name="battery_info_status_not_charging" msgid="1103084691314264664">"Povezano, ali se ne puni"</string> <string name="battery_info_status_full" msgid="1339002294876531312">"Napunjeno"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Posve puna"</string> + <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Punjenje na čekanju"</string> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Kontrolira administrator"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Kontrolira ograničena postavka"</string> <string name="disabled" msgid="8017887509554714950">"Onemogućeno"</string> diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml index 68ff9ae62d18..2ffb08caecca 100644 --- a/packages/SettingsLib/res/values-hu/strings.xml +++ b/packages/SettingsLib/res/values-hu/strings.xml @@ -154,6 +154,7 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Képalkotó"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Fejhallgató"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Beviteli periféria"</string> + <string name="bluetooth_talkback_hearing_aids" msgid="3983279945542595479">"Hallókészülékek"</string> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wi-Fi kikapcsolva."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Nincs Wi-Fi-kapcsolat."</string> @@ -455,6 +456,8 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"A színjavítás funkció például a következő esetekben lehet hasznos:<br/> <ol> <li>&nbsp;Ha jobban szeretné látni a színeket.</li> <li>&nbsp;Ha a lényeges részek kiemelése érdekében el szeretne távolítani bizonyos színeket.</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Felülírva erre: <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <string name="power_charging_on_hold_settings_home_page" msgid="7690464049464805856">"<xliff:g id="LEVEL">%1$s</xliff:g> – Az akkumulátor védelme érdekében a töltés szünetel"</string> + <string name="power_incompatible_charging_settings_home_page" msgid="1261756225093962684">"<xliff:g id="LEVEL">%1$s</xliff:g> – Akkumulátortartozék ellenőrzése…"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Körülbelül <xliff:g id="TIME_REMAINING">%1$s</xliff:g> maradt hátra"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"Körülbelül <xliff:g id="TIME_REMAINING">%1$s</xliff:g> maradt hátra (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"Körülbelül <xliff:g id="TIME_REMAINING">%1$s</xliff:g> maradt hátra az eszköz használata alapján"</string> @@ -483,9 +486,10 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Vezeték nélküli töltés"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Töltés…"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"Nem tölt"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Csatlakoztatva, nem töltődik"</string> + <string name="battery_info_status_not_charging" msgid="1103084691314264664">"Csatlakoztatva, de nem tölt"</string> <string name="battery_info_status_full" msgid="1339002294876531312">"Feltöltve"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Teljesen feltöltve"</string> + <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"A töltés szünetel"</string> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Rendszergazda által irányítva"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Korlátozott beállítás vezérli"</string> <string name="disabled" msgid="8017887509554714950">"Letiltva"</string> diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml index f3061a704f0b..8bc6f667f241 100644 --- a/packages/SettingsLib/res/values-hy/strings.xml +++ b/packages/SettingsLib/res/values-hy/strings.xml @@ -154,6 +154,8 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Պատկերներ"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Ականջակալ"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Մուտքի արտաքին սարքեր"</string> + <!-- no translation found for bluetooth_talkback_hearing_aids (3983279945542595479) --> + <skip /> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wi-Fi-ն անջատված է:"</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wi-Fi-ը կապակցված չէ:"</string> @@ -455,6 +457,10 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Գունաշտկումը կարող է օգնել, երբ դուք ուզում եք՝<br/> <ol> <li>&nbsp;Ավելի հստակ տեսնել գույները</li> <li>&nbsp;Հեռացնել գույները, որպեսզի կարողանաք կենտրոնանալ</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Գերազանցված է <xliff:g id="TITLE">%1$s</xliff:g>-ից"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_on_hold_settings_home_page (7690464049464805856) --> + <skip /> + <!-- no translation found for power_incompatible_charging_settings_home_page (1261756225093962684) --> + <skip /> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Լիցքը կբավարարի մոտ <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"Լիցքը (<xliff:g id="LEVEL">%2$s</xliff:g>) կբավարարի մոտ <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"Լիցքը կբավարարի մոտ <xliff:g id="TIME_REMAINING">%1$s</xliff:g>՝ կախված օգտագործման եղանակից"</string> @@ -483,9 +489,12 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Անլար լիցքավորում"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Լիցքավորում"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"Չի լիցքավորվում"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Միացված է, չի լիցքավորվում"</string> + <!-- no translation found for battery_info_status_not_charging (1103084691314264664) --> + <skip /> <string name="battery_info_status_full" msgid="1339002294876531312">"Լիցքավորված է"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Լրիվ լիցքավորված է"</string> + <!-- no translation found for battery_info_status_charging_on_hold (6364355145521694438) --> + <skip /> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Վերահսկվում է ադմինիստրատորի կողմից"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Կառավարվում է սահմանափակ ռեժիմի կարգավորումներով"</string> <string name="disabled" msgid="8017887509554714950">"Կասեցված է"</string> diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml index 2c166039b38a..2f27c62c0e4e 100644 --- a/packages/SettingsLib/res/values-in/strings.xml +++ b/packages/SettingsLib/res/values-in/strings.xml @@ -154,6 +154,8 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Pencitraan"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Headphone"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Periferal Masukan"</string> + <!-- no translation found for bluetooth_talkback_hearing_aids (3983279945542595479) --> + <skip /> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wi-Fi tidak aktif."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wi-Fi tidak terhubung."</string> @@ -455,6 +457,10 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Koreksi warna dapat berguna jika Anda ingin:<br/> <ol> <li> Melihat warna dengan lebih akurat</li> <li> Menghapus warna agar Anda lebih fokus</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Digantikan oleh <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_on_hold_settings_home_page (7690464049464805856) --> + <skip /> + <!-- no translation found for power_incompatible_charging_settings_home_page (1261756225093962684) --> + <skip /> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Sekitar <xliff:g id="TIME_REMAINING">%1$s</xliff:g> lagi"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"Sekitar <xliff:g id="TIME_REMAINING">%1$s</xliff:g> lagi (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"Sekitar <xliff:g id="TIME_REMAINING">%1$s</xliff:g> lagi berdasarkan penggunaan Anda"</string> @@ -483,9 +489,12 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Mengisi daya nirkabel"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Pengisian daya"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"Tidak mengisi daya"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Terhubung, tidak mengisi daya"</string> + <!-- no translation found for battery_info_status_not_charging (1103084691314264664) --> + <skip /> <string name="battery_info_status_full" msgid="1339002294876531312">"Terisi"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Baterai Terisi Penuh"</string> + <!-- no translation found for battery_info_status_charging_on_hold (6364355145521694438) --> + <skip /> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Dikontrol oleh admin"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Dikontrol oleh Setelan Terbatas"</string> <string name="disabled" msgid="8017887509554714950">"Dinonaktifkan"</string> diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml index 09587eee5b04..c2d6de3fae42 100644 --- a/packages/SettingsLib/res/values-is/strings.xml +++ b/packages/SettingsLib/res/values-is/strings.xml @@ -154,6 +154,8 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Myndherming"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Heyrnartól"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Jaðartæki með inntak"</string> + <!-- no translation found for bluetooth_talkback_hearing_aids (3983279945542595479) --> + <skip /> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Slökkt á Wi-Fi."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wi-Fi ótengt."</string> @@ -455,6 +457,10 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Litaleiðrétting kemur m.a. að gagni þegar þú vilt:<br/> <ol> <li>&nbsp;Sjá liti í aukinni skerpu</li> <li>&nbsp;Fjarlægja liti til að geta einbeitt þér betur</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Hnekkt af <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_on_hold_settings_home_page (7690464049464805856) --> + <skip /> + <!-- no translation found for power_incompatible_charging_settings_home_page (1261756225093962684) --> + <skip /> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Um það bil <xliff:g id="TIME_REMAINING">%1$s</xliff:g> eftir"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"Um það bil <xliff:g id="TIME_REMAINING">%1$s</xliff:g> eftir (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"Um það bil <xliff:g id="TIME_REMAINING">%1$s</xliff:g> eftir miðað við notkun þína"</string> @@ -483,9 +489,12 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Hleður þráðlaust"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Í hleðslu"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"Ekki í hleðslu"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Tengt, ekki í hleðslu"</string> + <!-- no translation found for battery_info_status_not_charging (1103084691314264664) --> + <skip /> <string name="battery_info_status_full" msgid="1339002294876531312">"Fullhlaðin"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Full hleðsla"</string> + <!-- no translation found for battery_info_status_charging_on_hold (6364355145521694438) --> + <skip /> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Stjórnað af kerfisstjóra"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Stýrt af takmarkaði stillingu"</string> <string name="disabled" msgid="8017887509554714950">"Óvirkt"</string> diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml index 98b2bd339993..27b23b7d79bf 100644 --- a/packages/SettingsLib/res/values-it/strings.xml +++ b/packages/SettingsLib/res/values-it/strings.xml @@ -154,6 +154,8 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Sistema di imaging"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Cuffie"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Periferica di immissione"</string> + <!-- no translation found for bluetooth_talkback_hearing_aids (3983279945542595479) --> + <skip /> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wi-Fi non attivo."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Rete Wi-Fi scollegata."</string> @@ -455,6 +457,10 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"La correzione del colore può essere utile quando vuoi:<br/> <ol> <li>&nbsp;Vedere i colori con più precisione</li> <li>&nbsp;Rimuovere i colori per mettere meglio a fuoco</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Valore sostituito da <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_on_hold_settings_home_page (7690464049464805856) --> + <skip /> + <!-- no translation found for power_incompatible_charging_settings_home_page (1261756225093962684) --> + <skip /> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Tempo rimanente: <xliff:g id="TIME_REMAINING">%1$s</xliff:g> circa"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"Tempo rimanente: <xliff:g id="TIME_REMAINING">%1$s</xliff:g> circa (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"Tempo rimanente in base al tuo utilizzo: <xliff:g id="TIME_REMAINING">%1$s</xliff:g> circa"</string> @@ -483,9 +489,12 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"In carica, wireless"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"In carica"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"Non in carica"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Dispositivo connesso, non in carica"</string> + <!-- no translation found for battery_info_status_not_charging (1103084691314264664) --> + <skip /> <string name="battery_info_status_full" msgid="1339002294876531312">"Carica"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Batteria completamente carica"</string> + <!-- no translation found for battery_info_status_charging_on_hold (6364355145521694438) --> + <skip /> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Gestita dall\'amministratore"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Gestita tramite impostazioni con restrizioni"</string> <string name="disabled" msgid="8017887509554714950">"Disattivato"</string> diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml index fbd715a40384..0c3c4f72945d 100644 --- a/packages/SettingsLib/res/values-iw/strings.xml +++ b/packages/SettingsLib/res/values-iw/strings.xml @@ -154,6 +154,8 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"הדמיה"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"אוזניות"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"ציוד קלט היקפי"</string> + <!-- no translation found for bluetooth_talkback_hearing_aids (3983279945542595479) --> + <skip /> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wi-Fi כבוי."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wi-Fi מנותק."</string> @@ -455,6 +457,10 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"תיקון הצבע יכול לעזור אם רוצים:<br/> <ol> <li>&nbsp;לראות צבעים מדויקים יותר</li> <li>&nbsp;לראות פחות צבעים כדי לשפר את הריכוז</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"נעקף על ידי <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_on_hold_settings_home_page (7690464049464805856) --> + <skip /> + <!-- no translation found for power_incompatible_charging_settings_home_page (1261756225093962684) --> + <skip /> <string name="power_remaining_duration_only" msgid="8264199158671531431">"הזמן הנותר: בערך <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"הזמן הנותר: בערך <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"הזמן הנותר על סמך השימוש שלך: בערך <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -483,9 +489,12 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"בטעינה אלחוטית"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"טעינה"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"לא בטעינה"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"מחובר, לא בטעינה"</string> + <!-- no translation found for battery_info_status_not_charging (1103084691314264664) --> + <skip /> <string name="battery_info_status_full" msgid="1339002294876531312">"הסוללה טעונה"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"טעונה במלואה"</string> + <!-- no translation found for battery_info_status_charging_on_hold (6364355145521694438) --> + <skip /> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"נמצא בשליטת מנהל מערכת"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"בשליטה של הגדרה מוגבלת"</string> <string name="disabled" msgid="8017887509554714950">"מושבת"</string> diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml index 5d578431e9ba..fbdca5407c1a 100644 --- a/packages/SettingsLib/res/values-ja/strings.xml +++ b/packages/SettingsLib/res/values-ja/strings.xml @@ -154,6 +154,7 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"画像"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"ヘッドフォン"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"入力用周辺機器"</string> + <string name="bluetooth_talkback_hearing_aids" msgid="3983279945542595479">"補聴器"</string> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wi-FiはOFFです。"</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wi-Fiが切断されました。"</string> @@ -455,6 +456,8 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"色補正は以下の場合に役立ちます。<br/> <ol> <li>&nbsp;色をより正確に表示したい場合</li> <li>&nbsp;はっきり読み取れるよう色を取り除きたい場合</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g>によって上書き済み"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <string name="power_charging_on_hold_settings_home_page" msgid="7690464049464805856">"<xliff:g id="LEVEL">%1$s</xliff:g> - バッテリーを保護するため、充電を一時停止しています"</string> + <string name="power_incompatible_charging_settings_home_page" msgid="1261756225093962684">"<xliff:g id="LEVEL">%1$s</xliff:g> - 充電用アクセサリを確認しています"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"残り時間: 約 <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"残り時間: 約 <xliff:g id="TIME_REMAINING">%1$s</xliff:g>(<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"残り時間: 約 <xliff:g id="TIME_REMAINING">%1$s</xliff:g>(使用状況に基づく)"</string> @@ -483,9 +486,10 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"ワイヤレス充電中"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"充電中"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"充電していません"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"接続済み、充電していません"</string> + <string name="battery_info_status_not_charging" msgid="1103084691314264664">"接続済み(充電していません)"</string> <string name="battery_info_status_full" msgid="1339002294876531312">"充電が完了しました"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"充電完了"</string> + <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"充電を一時停止しています"</string> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"管理者により管理されています"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"制限付き設定によって管理されています"</string> <string name="disabled" msgid="8017887509554714950">"無効"</string> diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml index eb89b19a4ea5..0f02b449b432 100644 --- a/packages/SettingsLib/res/values-ka/strings.xml +++ b/packages/SettingsLib/res/values-ka/strings.xml @@ -154,6 +154,7 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"გამოსახულებათა დამუშავების მოწყობილობა"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"ყურსასმენი"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"შეყვანის პერიფერიული მოწყობილობა"</string> + <string name="bluetooth_talkback_hearing_aids" msgid="3983279945542595479">"სმენის მოწყობილობები"</string> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"WiFi გამორთულია."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"WiFi არ არის დაკავშირებული."</string> @@ -455,6 +456,8 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"ფერთა კორექცია შეიძლება დაგეხმაროთ, როცა გსურთ:<br/> <ol> <li>&nbsp;ფერების მეტი სიზუსტით დანახვა</li> <li>&nbsp;ფერების მოცილება, რომ უკეთ კონცენტრირდეთ</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"უკუგებულია <xliff:g id="TITLE">%1$s</xliff:g>-ის მიერ"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <string name="power_charging_on_hold_settings_home_page" msgid="7690464049464805856">"<xliff:g id="LEVEL">%1$s</xliff:g> – დატენვა შეჩერებულია ბატარეის დასაცავად"</string> + <string name="power_incompatible_charging_settings_home_page" msgid="1261756225093962684">"<xliff:g id="LEVEL">%1$s</xliff:g> – მიმდინარეობს დამტენი აქსესუარის შემოწმება"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"დარჩა დაახლოებით <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"დარჩა დაახლოებით <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"დარჩა დაახლოებით <xliff:g id="TIME_REMAINING">%1$s</xliff:g>, ბატარეის მოხმარების გათვალისწინებით"</string> @@ -483,9 +486,10 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"უსადენოდ დატენა"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"იტენება"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"არ იტენება"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"დაკავშირებულია, არ იტენება"</string> + <string name="battery_info_status_not_charging" msgid="1103084691314264664">"დაკავშირებულია, მაგრამ არ იტენება"</string> <string name="battery_info_status_full" msgid="1339002294876531312">"დატენილია"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"ბოლომდე დატენილი"</string> + <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"დატენვა შეჩერებულია"</string> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"იმართება ადმინისტრატორის მიერ"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"კონტროლდება შეზღუდული რეჟიმის პარამეტრით"</string> <string name="disabled" msgid="8017887509554714950">"გამორთული"</string> diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml index a8fb9aa6054d..3f71b391303b 100644 --- a/packages/SettingsLib/res/values-kk/strings.xml +++ b/packages/SettingsLib/res/values-kk/strings.xml @@ -154,6 +154,8 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Бейне құралы"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Құлақаспап"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Кіріс құралы"</string> + <!-- no translation found for bluetooth_talkback_hearing_aids (3983279945542595479) --> + <skip /> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wi-Fi өшірулі."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wi-Fi ажыратылған."</string> @@ -455,6 +457,10 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Түсті түзету мына жағдайларда пайдалы болуы мүмкін:<br/> <ol> <li>&nbsp;түстерді анығырақ көру;</li> <li>&nbsp;зейін қоюға көмектесу үшін түстерді алып тастау.</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> үстінен басқан"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_on_hold_settings_home_page (7690464049464805856) --> + <skip /> + <!-- no translation found for power_incompatible_charging_settings_home_page (1261756225093962684) --> + <skip /> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Шамамен <xliff:g id="TIME_REMAINING">%1$s</xliff:g> қалды"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"Шамамен <xliff:g id="TIME_REMAINING">%1$s</xliff:g> қалды (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"Пайдалану деректеріңізге сәйкес енді шамамен <xliff:g id="TIME_REMAINING">%1$s</xliff:g> қалды"</string> @@ -483,9 +489,12 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Сымсыз зарядталуда"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Зарядталып жатыр."</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"Зарядталу орындалып жатқан жоқ"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Жалғанған, зарядталып жатқан жоқ"</string> + <!-- no translation found for battery_info_status_not_charging (1103084691314264664) --> + <skip /> <string name="battery_info_status_full" msgid="1339002294876531312">"Зарядталды"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Толық зарядталды."</string> + <!-- no translation found for battery_info_status_charging_on_hold (6364355145521694438) --> + <skip /> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Әкімші басқарады"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Шектелген параметрлер арқылы басқарылады."</string> <string name="disabled" msgid="8017887509554714950">"Өшірілген"</string> diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml index 16f14ff6c906..bf8870763a6a 100644 --- a/packages/SettingsLib/res/values-km/strings.xml +++ b/packages/SettingsLib/res/values-km/strings.xml @@ -154,6 +154,7 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"កំពុងបង្ហាញ"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"កាស"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"ធាតុបញ្ចូលបន្ថែម"</string> + <string name="bluetooth_talkback_hearing_aids" msgid="3983279945542595479">"ឧបករណ៍ជំនួយការស្ដាប់"</string> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"ប៊្លូធូស"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"បានបិទ Wifi"</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"បានផ្តាច់ Wifi"</string> @@ -455,6 +456,8 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"ការកែតម្រូវពណ៌អាចមានប្រយោជន៍ នៅពេលអ្នកចង់៖<br/> <ol> <li>&nbsp;មើលពណ៌កាន់តែត្រឹមត្រូវ</li> <li>&nbsp;លុបពណ៌ចេញ ដើម្បីជួយឱ្យអ្នកផ្ដោតអារម្មណ៍</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"បដិសេធដោយ <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <string name="power_charging_on_hold_settings_home_page" msgid="7690464049464805856">"<xliff:g id="LEVEL">%1$s</xliff:g> - កំពុងផ្អាកការសាកថ្ម ដើម្បីការពារថ្ម"</string> + <string name="power_incompatible_charging_settings_home_page" msgid="1261756225093962684">"<xliff:g id="LEVEL">%1$s</xliff:g> - កំពុងពិនិត្យមើលគ្រឿងសាកថ្ម"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"នៅសល់ប្រហែល <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ទៀត"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"នៅសល់ប្រហែល <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ទៀត (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"នៅសល់ប្រហែល <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ទៀត ផ្អែកលើការប្រើប្រាស់របស់អ្នក"</string> @@ -483,9 +486,10 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"កំពុងសាកថ្មឥតខ្សែ"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"កំពុងសាកថ្ម"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"មិនកំពុងសាកថ្ម"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"បានភ្ជាប់ មិនកំពុងសាកថ្ម"</string> + <string name="battery_info_status_not_charging" msgid="1103084691314264664">"បានភ្ជាប់ តែមិនកំពុងសាកថ្មទេ"</string> <string name="battery_info_status_full" msgid="1339002294876531312">"បានសាកថ្មពេញ"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"បានសាកថ្មពេញ"</string> + <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"កំពុងផ្អាកការសាកថ្ម"</string> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"គ្រប់គ្រងដោយអ្នកគ្រប់គ្រង"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"គ្រប់គ្រងដោយការកំណត់ដែលបានរឹតបន្តឹង"</string> <string name="disabled" msgid="8017887509554714950">"បិទ"</string> diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml index 071258d593e4..e7f0220d3cc6 100644 --- a/packages/SettingsLib/res/values-kn/strings.xml +++ b/packages/SettingsLib/res/values-kn/strings.xml @@ -154,6 +154,8 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"ಇಮೇಜಿಂಗ್"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"ಹೆಡ್ಫೋನ್"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"ಪೆರಿಪೆರಲ್ ಇನ್ಪುಟ್"</string> + <!-- no translation found for bluetooth_talkback_hearing_aids (3983279945542595479) --> + <skip /> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"ಬ್ಲೂಟೂತ್"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"ವೈಫೈ ಆಫ್."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"ವೈಫೈ ಸಂಪರ್ಕ ಕಡಿತಗೊಂಡಿದೆ."</string> @@ -455,6 +457,10 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"ನೀವು ಹೆಚ್ಚು ಸ್ಪಷ್ಟವಾದ ಬಣ್ಣಗಳನ್ನು ನೋಡಲು ಬಯಸಿದರೆ :<br/> <ol> <li>&nbsp; ಬಣ್ಣದ ತಿದ್ದುಪಡಿಯು ಸಹಾಯಕವಾಗಿರುತ್ತದೆ; ಗಮನವನ್ನು ಕೇಂದ್ರೀಕರಿಸಲು ನಿಮಗೆ ಸಹಾಯ ಮಾಡಲು ಬಣ್ಣಗಳನ್ನು ತೆಗೆದುಹಾಕಿ </li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> ಮೂಲಕ ಅತಿಕ್ರಮಿಸುತ್ತದೆ"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_on_hold_settings_home_page (7690464049464805856) --> + <skip /> + <!-- no translation found for power_incompatible_charging_settings_home_page (1261756225093962684) --> + <skip /> <string name="power_remaining_duration_only" msgid="8264199158671531431">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> ಸಮಯ ಬಾಕಿ ಉಳಿದಿದೆ"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"(<xliff:g id="LEVEL">%2$s</xliff:g>) ತಲುಪಲು <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ಸಮಯ ಬಾಕಿ ಉಳಿದಿದೆ"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"ನಿಮ್ಮ ಬಳಕೆಯ ಆಧಾರದ ಮೇಲೆ ಸುಮಾರು <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ಸಮಯ ಬಾಕಿ ಉಳಿದಿದೆ"</string> @@ -483,9 +489,12 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"ವೈರ್ಲೆಸ್ ಚಾರ್ಜಿಂಗ್"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"ಚಾರ್ಜ್ ಆಗುತ್ತಿಲ್ಲ"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"ಕನೆಕ್ಟ್ ಆಗಿದೆ, ಚಾರ್ಜ್ ಆಗುತ್ತಿಲ್ಲ"</string> + <!-- no translation found for battery_info_status_not_charging (1103084691314264664) --> + <skip /> <string name="battery_info_status_full" msgid="1339002294876531312">"ಚಾರ್ಜ್ ಆಗಿದೆ"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"ಪೂರ್ಣವಾಗಿ ಚಾರ್ಜ್ ಆಗಿದೆ"</string> + <!-- no translation found for battery_info_status_charging_on_hold (6364355145521694438) --> + <skip /> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"ನಿರ್ವಾಹಕರ ಮೂಲಕ ನಿಯಂತ್ರಿಸಲಾಗಿದೆ"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"ನಿರ್ಬಂಧಿಸಲಾದ ಸೆಟ್ಟಿಂಗ್ ಮೂಲಕ ನಿಯಂತ್ರಿಸಲಾಗುತ್ತದೆ"</string> <string name="disabled" msgid="8017887509554714950">"ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string> diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml index 1bf0a5130f32..df4349417358 100644 --- a/packages/SettingsLib/res/values-ko/strings.xml +++ b/packages/SettingsLib/res/values-ko/strings.xml @@ -154,6 +154,8 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"이미징"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"헤드폰"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"입력 주변기기"</string> + <!-- no translation found for bluetooth_talkback_hearing_aids (3983279945542595479) --> + <skip /> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"블루투스"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wi-Fi가 꺼져 있습니다."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wi-Fi 연결이 끊어졌습니다."</string> @@ -455,6 +457,10 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"색상 보정은 다음과 같은 경우에 유용할 수 있습니다.<br/> <ol> <li>&nbsp;색상을 보다 정확하게 확인하려는 경우</li> <li>&nbsp;집중에 도움이 되도록 색상을 제거하려는 경우</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> 우선 적용됨"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g>, <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_on_hold_settings_home_page (7690464049464805856) --> + <skip /> + <!-- no translation found for power_incompatible_charging_settings_home_page (1261756225093962684) --> + <skip /> <string name="power_remaining_duration_only" msgid="8264199158671531431">"남은 시간: 약 <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"남은 시간 약 <xliff:g id="TIME_REMAINING">%1$s</xliff:g>(<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"내 사용량을 기준으로 약 <xliff:g id="TIME_REMAINING">%1$s</xliff:g> 남음"</string> @@ -483,9 +489,12 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"무선 충전 중"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"충전"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"충전 안함"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"연결됨, 충전 중 아님"</string> + <!-- no translation found for battery_info_status_not_charging (1103084691314264664) --> + <skip /> <string name="battery_info_status_full" msgid="1339002294876531312">"충전됨"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"완전히 충전됨"</string> + <!-- no translation found for battery_info_status_charging_on_hold (6364355145521694438) --> + <skip /> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"관리자가 제어"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"제한된 설정으로 제어됨"</string> <string name="disabled" msgid="8017887509554714950">"사용 안함"</string> diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml index 9565fb0ce64b..6e6926edf98a 100644 --- a/packages/SettingsLib/res/values-ky/strings.xml +++ b/packages/SettingsLib/res/values-ky/strings.xml @@ -154,6 +154,8 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Сүрөт тартуучу түзмөк"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Кулакчын"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Дайындарды киргизүүчү тышкы түзмөк"</string> + <!-- no translation found for bluetooth_talkback_hearing_aids (3983279945542595479) --> + <skip /> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wifi өчүк."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wifi туташуусу жок."</string> @@ -455,6 +457,10 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Түстөрдү тууралоо менен:<br/> <ol> <li>&nbsp;Керектүү түстөрдү аласыз</li> <li>&nbsp;Алагды кылган түстөрдү өчүрүп саласыз</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> менен алмаштырылган"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_on_hold_settings_home_page (7690464049464805856) --> + <skip /> + <!-- no translation found for power_incompatible_charging_settings_home_page (1261756225093962684) --> + <skip /> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Болжол менен <xliff:g id="TIME_REMAINING">%1$s</xliff:g> калды"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"Болжол менен <xliff:g id="TIME_REMAINING">%1$s</xliff:g> калды (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"Колдонгонуңузга караганда болжол менен <xliff:g id="TIME_REMAINING">%1$s</xliff:g> калды"</string> @@ -483,9 +489,12 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Зымсыз кубатталууда"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Кубатталууда"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"Кубат алган жок"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Туташты, кубатталган жок"</string> + <!-- no translation found for battery_info_status_not_charging (1103084691314264664) --> + <skip /> <string name="battery_info_status_full" msgid="1339002294876531312">"Кубатталды"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Толук кубатталды"</string> + <!-- no translation found for battery_info_status_charging_on_hold (6364355145521694438) --> + <skip /> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Администратор тарабынан көзөмөлдөнөт"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Чектелген параметр аркылуу көзөмөлдөнөт"</string> <string name="disabled" msgid="8017887509554714950">"Өчүрүлгөн"</string> diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml index 23f249a0dfc4..4e47201d7dee 100644 --- a/packages/SettingsLib/res/values-lo/strings.xml +++ b/packages/SettingsLib/res/values-lo/strings.xml @@ -154,6 +154,7 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"ຮູບພາບ"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"ຫູຟັງ"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"ອຸປະກອນພ່ວງອິນພຸດ"</string> + <string name="bluetooth_talkback_hearing_aids" msgid="3983279945542595479">"ເຄື່ອງຊ່ວຍຟັງ"</string> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"WiFi ປິດຢູ່."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"ຕັດການເຊື່ອມຕໍ່ Wi-Fi ແລ້ວ."</string> @@ -455,6 +456,8 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"ການແກ້ໄຂສີອາດມີປະໂຫຍດໃນເວລາທີ່ທ່ານຕ້ອງການ:<br/> <ol> <li>&nbsp;ເບິ່ງສີໃຫ້ມີຄວາມຖືກຕ້ອງຫຼາຍຂຶ້ນ</li> <li>&nbsp;ລຶບສີອອກເພື່ອຊ່ວຍທ່ານໂຟກັສ</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"ຖືກແທນໂດຍ <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <string name="power_charging_on_hold_settings_home_page" msgid="7690464049464805856">"<xliff:g id="LEVEL">%1$s</xliff:g> - ຢຸດການສາກຊົ່ວຄາວເພື່ອປົກປ້ອງແບັດເຕີຣີ"</string> + <string name="power_incompatible_charging_settings_home_page" msgid="1261756225093962684">"<xliff:g id="LEVEL">%1$s</xliff:g> - ກຳລັງກວດສອບອຸປະກອນເສີມສຳລັບການສາກ"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"ເຫຼືອອີກປະມານ <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"ເຫຼືອອີກປະມານ <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"ເຫຼືອອີກປະມານ <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ອ້າງອີງຈາກການນຳໃຊ້ຂອງທ່ານ"</string> @@ -483,9 +486,10 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"ກຳລັງສາກໄຟໄຮ້ສາຍ"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"ກຳລັງສາກໄຟ"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"ບໍ່ໄດ້ສາກໄຟ"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"ເຊື່ອມຕໍ່ແລ້ວ, ບໍ່ໄດ້ສາກໄຟ"</string> + <string name="battery_info_status_not_charging" msgid="1103084691314264664">"ເຊື່ອມຕໍ່ແລ້ວ, ແຕ່ຍັງບໍ່ສາກ"</string> <string name="battery_info_status_full" msgid="1339002294876531312">"ສາກເຕັມແລ້ວ"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"ສາກເຕັມແລ້ວ"</string> + <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"ຢຸດການສາກຊົ່ວຄາວ"</string> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"ຄວບຄຸມໂດຍຜູ້ເບິ່ງແຍງ"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"ຄວບຄຸມໂດຍການຕັ້ງຄ່າທີ່ຈຳກັດໄວ້"</string> <string name="disabled" msgid="8017887509554714950">"ປິດການນຳໃຊ້"</string> diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml index f529ca48deb9..5e2f696ab0cd 100644 --- a/packages/SettingsLib/res/values-lt/strings.xml +++ b/packages/SettingsLib/res/values-lt/strings.xml @@ -154,6 +154,8 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Vaizdavimo įrenginys"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Ausinės"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Išorinis įvesties įrenginys"</string> + <!-- no translation found for bluetooth_talkback_hearing_aids (3983279945542595479) --> + <skip /> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"„Wi-Fi“ išjungtas."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"„Wi-Fi“ atjungtas."</string> @@ -455,6 +457,10 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Spalvų taisymas gali būti naudingas, kai norite:<br/> <ol> <li>&nbsp;aiškiau matyti spalvas;</li> <li>&nbsp;pašalinti spalvas, kad galėtumėte sutelkti dėmesį.</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Nepaisyta naudojant nuostatą „<xliff:g id="TITLE">%1$s</xliff:g>“"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_on_hold_settings_home_page (7690464049464805856) --> + <skip /> + <!-- no translation found for power_incompatible_charging_settings_home_page (1261756225093962684) --> + <skip /> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Liko maždaug <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"Liko maždaug <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"Liko maždaug <xliff:g id="TIME_REMAINING">%1$s</xliff:g>, atsižvelgiant į naudojimą"</string> @@ -483,9 +489,12 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Kraunama be laidų"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Įkraunama"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"Nekraunama"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Prijungta, neįkraunama"</string> + <!-- no translation found for battery_info_status_not_charging (1103084691314264664) --> + <skip /> <string name="battery_info_status_full" msgid="1339002294876531312">"Įkrauta"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Visiškai įkrautas"</string> + <!-- no translation found for battery_info_status_charging_on_hold (6364355145521694438) --> + <skip /> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Valdo administratorius"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Valdoma pagal apribotą nustatymą"</string> <string name="disabled" msgid="8017887509554714950">"Neleidžiama"</string> diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml index 24be0aaef92f..f9bab6fe0d4a 100644 --- a/packages/SettingsLib/res/values-lv/strings.xml +++ b/packages/SettingsLib/res/values-lv/strings.xml @@ -154,6 +154,8 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Attēlu apstrādes ierīce"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Austiņas"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Ievades ierīce"</string> + <!-- no translation found for bluetooth_talkback_hearing_aids (3983279945542595479) --> + <skip /> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wi-Fi savienojums izslēgts"</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wi-Fi savienojums pārtraukts"</string> @@ -455,6 +457,10 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Krāsu korekcija var būt noderīga šādiem mērķiem:<br/> <ol> <li>&nbsp;precīzākai krāsu attēlošanai;</li> <li>&nbsp;krāsu noņemšanai, lai būtu vieglāk koncentrēties.</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Jaunā preference: <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> — <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_on_hold_settings_home_page (7690464049464805856) --> + <skip /> + <!-- no translation found for power_incompatible_charging_settings_home_page (1261756225093962684) --> + <skip /> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Aptuvenais atlikušais laiks: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"Aptuvenais atlikušais laiks: <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"Ņemot vērā lietojumu, atlikušais laiks: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -483,9 +489,12 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Bezvadu uzlāde"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Notiek uzlāde"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"Nenotiek uzlāde"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Ierīce pievienota, uzlāde nenotiek"</string> + <!-- no translation found for battery_info_status_not_charging (1103084691314264664) --> + <skip /> <string name="battery_info_status_full" msgid="1339002294876531312">"Uzlādēts"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Pilnībā uzlādēts"</string> + <!-- no translation found for battery_info_status_charging_on_hold (6364355145521694438) --> + <skip /> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Kontrolē administrators"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Kontrolē ierobežots iestatījums"</string> <string name="disabled" msgid="8017887509554714950">"Atspējots"</string> diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml index 030a438576b0..aafa8463871f 100644 --- a/packages/SettingsLib/res/values-mk/strings.xml +++ b/packages/SettingsLib/res/values-mk/strings.xml @@ -154,6 +154,8 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Слики"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Слушалка"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Периферен влез"</string> + <!-- no translation found for bluetooth_talkback_hearing_aids (3983279945542595479) --> + <skip /> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wi-Fi е исклучено."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wi-Fi е исклучено."</string> @@ -455,6 +457,10 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Корекцијата на боите може да биде корисна кога сакате:<br/> <ol> <li>&nbsp;да ги гледате боите попрецизно</li> <li>&nbsp;да ги отстраните боите за полесно да се концентрирате</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Прескокнато според <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_on_hold_settings_home_page (7690464049464805856) --> + <skip /> + <!-- no translation found for power_incompatible_charging_settings_home_page (1261756225093962684) --> + <skip /> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Уште околу <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"Уште околу <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"Уште околу <xliff:g id="TIME_REMAINING">%1$s</xliff:g> според вашето користење"</string> @@ -483,9 +489,12 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Се полни безжично"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Се полни"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"Не се полни"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Поврзано, не се полни"</string> + <!-- no translation found for battery_info_status_not_charging (1103084691314264664) --> + <skip /> <string name="battery_info_status_full" msgid="1339002294876531312">"Полна"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Целосно полна"</string> + <!-- no translation found for battery_info_status_charging_on_hold (6364355145521694438) --> + <skip /> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Контролирано од администраторот"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Контролирано со ограничени поставки"</string> <string name="disabled" msgid="8017887509554714950">"Оневозможено"</string> diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml index 9a01b5333d7c..947ab917881e 100644 --- a/packages/SettingsLib/res/values-ml/strings.xml +++ b/packages/SettingsLib/res/values-ml/strings.xml @@ -154,6 +154,7 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"ഇമേജിംഗ്"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"ഹെഡ്ഫോൺ"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"ഇൻപുട്ട് പെരിഫറൽ"</string> + <string name="bluetooth_talkback_hearing_aids" msgid="3983279945542595479">"ശ്രവണ സഹായികൾ"</string> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"വൈഫൈ ഓഫാണ്."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"വൈഫൈ വിച്ഛേദിച്ചു."</string> @@ -455,6 +456,8 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"ഇനിപ്പറയുന്ന കാര്യങ്ങൾ ചെയ്യാൻ ആഗ്രഹിക്കുമ്പോൾ നിറം ശരിയാക്കൽ സഹായകരമാകും:<br/> <ol> <li>&nbsp;നിറങ്ങൾ കൂടുതൽ കൃത്യമായി കാണാൻ</li> <li>&nbsp;ഫോക്കസ് ചെയ്യാൻ നിങ്ങളെ സഹായിക്കുന്നതിന് നിറങ്ങൾ നീക്കം ചെയ്യാൻ</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> ഉപയോഗിച്ച് അസാധുവാക്കി"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <string name="power_charging_on_hold_settings_home_page" msgid="7690464049464805856">"<xliff:g id="LEVEL">%1$s</xliff:g> - ബാറ്ററി പരിരക്ഷിക്കാൻ ചാർജിംഗ് ഹോൾഡിലാണ്"</string> + <string name="power_incompatible_charging_settings_home_page" msgid="1261756225093962684">"<xliff:g id="LEVEL">%1$s</xliff:g> - ചാർജിംഗ് ആക്സസറി പരിശോധിക്കുന്നു"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"ഏതാണ്ട് <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ശേഷിക്കുന്നു"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"ഏതാണ്ട് <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ശേഷിക്കുന്നു (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"നിങ്ങളുടെ ഉപയോഗത്തെ അടിസ്ഥാനമാക്കി ഏതാണ്ട് <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ശേഷിക്കുന്നു"</string> @@ -483,9 +486,10 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"വയർലെസായി ചാർജുചെയ്യുന്നു"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"ചാർജ് ചെയ്യുന്നു"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"ചാർജ്ജുചെയ്യുന്നില്ല"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"കണക്റ്റ് ചെയ്തിരിക്കുന്നു, ചാർജ് ചെയ്യുന്നില്ല"</string> + <string name="battery_info_status_not_charging" msgid="1103084691314264664">"കണക്റ്റ് ചെയ്തു, എന്നാൽ ചാർജ് ചെയ്യുന്നില്ല"</string> <string name="battery_info_status_full" msgid="1339002294876531312">"ചാർജായി"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"പൂർണ്ണമായി ചാർജ് ചെയ്തു"</string> + <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"ചാർജിംഗ് ഹോൾഡിലാണ്"</string> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"അഡ്മിൻ നിയന്ത്രിക്കുന്നത്"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"നിയന്ത്രിത ക്രമീകരണം ഉപയോഗിച്ച് നിയന്ത്രിക്കുന്നത്"</string> <string name="disabled" msgid="8017887509554714950">"പ്രവർത്തനരഹിതമാക്കി"</string> diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml index 03fecc411d9d..c857a2b3d9e8 100644 --- a/packages/SettingsLib/res/values-mn/strings.xml +++ b/packages/SettingsLib/res/values-mn/strings.xml @@ -154,6 +154,8 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Зураглал"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Чихэвч"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Нэмэлт оролт"</string> + <!-- no translation found for bluetooth_talkback_hearing_aids (3983279945542595479) --> + <skip /> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wifi унтраалттай байна."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wifi холбогдоогүй байна."</string> @@ -455,6 +457,10 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Өнгө тохируулга нь таныг дараахыг хийхийг хүсэх үед хэрэгтэй байж болно:<br/> <ol> <li>&nbsp;Өнгөнүүдийг илүү нарийвчилж харах</li> <li>&nbsp;Төвлөрөхийн тулд өнгөнүүдийг хасах</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Давхарласан <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_on_hold_settings_home_page (7690464049464805856) --> + <skip /> + <!-- no translation found for power_incompatible_charging_settings_home_page (1261756225093962684) --> + <skip /> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Ойролцоогоор <xliff:g id="TIME_REMAINING">%1$s</xliff:g> үлдсэн"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"Ойролцоогоор <xliff:g id="TIME_REMAINING">%1$s</xliff:g> үлдсэн (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"Таны хэрэглээнд үндэслэн ойролцоогоор <xliff:g id="TIME_REMAINING">%1$s</xliff:g> үлдсэн"</string> @@ -483,9 +489,12 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Утасгүй цэнэглэж байна"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Цэнэглэж байна"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"Цэнэглэхгүй байна"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Холбогдсон, цэнэглээгүй байна"</string> + <!-- no translation found for battery_info_status_not_charging (1103084691314264664) --> + <skip /> <string name="battery_info_status_full" msgid="1339002294876531312">"Цэнэглэсэн"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Бүрэн цэнэглэсэн"</string> + <!-- no translation found for battery_info_status_charging_on_hold (6364355145521694438) --> + <skip /> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Админ удирдсан"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Хязгаарлагдсан тохиргоогоор хянадаг"</string> <string name="disabled" msgid="8017887509554714950">"Идэвхгүйжүүлсэн"</string> diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml index e4edf088a002..26669b9df4b3 100644 --- a/packages/SettingsLib/res/values-mr/strings.xml +++ b/packages/SettingsLib/res/values-mr/strings.xml @@ -154,6 +154,8 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"इमेज"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"हेडफोन"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"इनपुट परिधीय"</string> + <!-- no translation found for bluetooth_talkback_hearing_aids (3983279945542595479) --> + <skip /> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"ब्लूटूथ"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"वाय-फाय बंद."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"वाय-फाय डिस्कनेक्ट झाले."</string> @@ -455,6 +457,10 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"तुम्हाला पुढील गोष्टी करायच्या असतील, तेव्हा रंग सुधारणेची मदत होऊ शकते:<br/> <ol> <li>&nbsp;रंग आणखी अचूकपणे पाहण्यासाठी</li> <li>&nbsp;तुम्हाला लक्ष केंद्रित करण्यात मदत करण्याकरिता रंग काढून टाकण्यासाठी</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> द्वारे अधिलिखित"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_on_hold_settings_home_page (7690464049464805856) --> + <skip /> + <!-- no translation found for power_incompatible_charging_settings_home_page (1261756225093962684) --> + <skip /> <string name="power_remaining_duration_only" msgid="8264199158671531431">"अंदाजे <xliff:g id="TIME_REMAINING">%1$s</xliff:g> बाकी आहे"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"अंदाजे <xliff:g id="TIME_REMAINING">%1$s</xliff:g> बाकी आहे (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"तुमच्या वापरावर आधारित अंदाजे <xliff:g id="TIME_REMAINING">%1$s</xliff:g> बाकी आहे"</string> @@ -483,9 +489,12 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"वायरलेसने चार्ज होत आहे"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"चार्ज होत आहे"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"चार्ज होत नाही"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"कनेक्ट केले, चार्ज होत नाही"</string> + <!-- no translation found for battery_info_status_not_charging (1103084691314264664) --> + <skip /> <string name="battery_info_status_full" msgid="1339002294876531312">"चार्ज झाली"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"पूर्ण चार्ज झाली"</string> + <!-- no translation found for battery_info_status_charging_on_hold (6364355145521694438) --> + <skip /> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"प्रशासकाने नियंत्रित केलेले"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"प्रतिबंधित केलेल्या सेटिंग द्वारे नियंत्रित"</string> <string name="disabled" msgid="8017887509554714950">"अक्षम"</string> diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml index 88f13f6f4797..dd31c8554364 100644 --- a/packages/SettingsLib/res/values-ms/strings.xml +++ b/packages/SettingsLib/res/values-ms/strings.xml @@ -154,6 +154,8 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Pengimejan"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Fon kepala"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Persisian Input"</string> + <!-- no translation found for bluetooth_talkback_hearing_aids (3983279945542595479) --> + <skip /> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wi-Fi dimatikan."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wi-Fi diputuskan sambungannya."</string> @@ -455,6 +457,10 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Pembetulan warna dapat membantu apabila anda mahu:<br/> <ol> <li>&nbsp;Melihat warna dengan lebih tepat</li> <li>&nbsp;Mengalih keluar warna agar anda dapat menumpukan perhatian</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Diatasi oleh <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_on_hold_settings_home_page (7690464049464805856) --> + <skip /> + <!-- no translation found for power_incompatible_charging_settings_home_page (1261756225093962684) --> + <skip /> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Kira-kira <xliff:g id="TIME_REMAINING">%1$s</xliff:g> lagi"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"Kira-kira <xliff:g id="TIME_REMAINING">%1$s</xliff:g> lagi (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"Kira-kira <xliff:g id="TIME_REMAINING">%1$s</xliff:g> lagi berdasarkan penggunaan anda"</string> @@ -483,9 +489,12 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Mengecas tanpa wayar"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Pengecasan"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"Tidak mengecas"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Bersambung, tidak mengecas"</string> + <!-- no translation found for battery_info_status_not_charging (1103084691314264664) --> + <skip /> <string name="battery_info_status_full" msgid="1339002294876531312">"Sudah dicas"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Dicas Penuh"</string> + <!-- no translation found for battery_info_status_charging_on_hold (6364355145521694438) --> + <skip /> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Dikawal oleh pentadbir"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Dikawal oleh Tetapan Terhad"</string> <string name="disabled" msgid="8017887509554714950">"Dilumpuhkan"</string> diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml index 58e2cf44bd0a..7c74e1bb1385 100644 --- a/packages/SettingsLib/res/values-my/strings.xml +++ b/packages/SettingsLib/res/values-my/strings.xml @@ -154,6 +154,8 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"ဓာတ်ပုံဆိုင်ရာ"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"နားကြပ်"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"ချိတ်ဆက်အသုံးပြုရသည့် စက်ပစ္စည်းများ"</string> + <!-- no translation found for bluetooth_talkback_hearing_aids (3983279945542595479) --> + <skip /> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"ဘလူးတုသ်"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wi-Fi ပိတ်ထားသည်"</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wi-Fi ချိတ်ဆက်ထားမှု မရှိပါ"</string> @@ -455,6 +457,10 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"အရောင် အမှန်ပြင်ခြင်းသည် အောက်ပါတို့အတွက် အသုံးဝင်နိုင်သည်-<br/> <ol> <li>&nbsp;အရောင်များကို ပိုမိုမှန်ကန်စွာ ကြည့်ရှုခြင်း</li> <li>&nbsp;အာရုံစိုက်နိုင်ရန် အရောင်များ ဖယ်ရှားခြင်း</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> မှ ကျော်၍ လုပ်ထားသည်။"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_on_hold_settings_home_page (7690464049464805856) --> + <skip /> + <!-- no translation found for power_incompatible_charging_settings_home_page (1261756225093962684) --> + <skip /> <string name="power_remaining_duration_only" msgid="8264199158671531431">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> ခန့် ကျန်သည်"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> ခန့် ကျန်သည် (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"သင်၏ အသုံးပြုမှု အပေါ် မူတည်၍ <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ခန့် ကျန်သည်"</string> @@ -483,9 +489,12 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"ကြိုးမဲ့ အားသွင်းနေသည်"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"အားသွင်းနေသည်"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"အားသွင်းမနေပါ"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"ချိတ်ဆက်ထားသည်၊ အားသွင်းမနေပါ"</string> + <!-- no translation found for battery_info_status_not_charging (1103084691314264664) --> + <skip /> <string name="battery_info_status_full" msgid="1339002294876531312">"အားသွင်းပြီးပါပြီ"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"အားအပြည့်သွင်းထားသည်"</string> + <!-- no translation found for battery_info_status_charging_on_hold (6364355145521694438) --> + <skip /> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"စီမံခန့်ခွဲသူမှ ထိန်းချုပ်ပါသည်"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"ကန့်သတ်ထားသော ဆက်တင်များဖြင့် ထိန်းချုပ်ထားသည်"</string> <string name="disabled" msgid="8017887509554714950">"ပိတ်ထားပြီး"</string> diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml index 08152682508e..4782f269158a 100644 --- a/packages/SettingsLib/res/values-nb/strings.xml +++ b/packages/SettingsLib/res/values-nb/strings.xml @@ -154,6 +154,8 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Bildefremviser"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Øretelefoner"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Inndata fra ytre utstyrsenheter"</string> + <!-- no translation found for bluetooth_talkback_hearing_aids (3983279945542595479) --> + <skip /> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wifi er av."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wifi er frakoblet."</string> @@ -455,6 +457,10 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Fargekorrigering kan være nyttig når du vil<br/> <ol> <li>&nbsp;se farger mer nøyaktig</li> <li>&nbsp;fjerne farger for å gjøre det enklere å fokusere</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Overstyres av <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_on_hold_settings_home_page (7690464049464805856) --> + <skip /> + <!-- no translation found for power_incompatible_charging_settings_home_page (1261756225093962684) --> + <skip /> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Omtrent <xliff:g id="TIME_REMAINING">%1$s</xliff:g> igjen"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"Omtrent <xliff:g id="TIME_REMAINING">%1$s</xliff:g> igjen (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"Omtrent <xliff:g id="TIME_REMAINING">%1$s</xliff:g> igjen basert på bruken din"</string> @@ -483,9 +489,12 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Lader trådløst"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Lader"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"Lader ikke"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Tilkoblet, lader ikke"</string> + <!-- no translation found for battery_info_status_not_charging (1103084691314264664) --> + <skip /> <string name="battery_info_status_full" msgid="1339002294876531312">"Ladet"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Fulladet"</string> + <!-- no translation found for battery_info_status_charging_on_hold (6364355145521694438) --> + <skip /> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Kontrollert av administratoren"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Kontrollert av en begrenset innstilling"</string> <string name="disabled" msgid="8017887509554714950">"Slått av"</string> diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml index 6c4ddf2a56a0..3a7da748c247 100644 --- a/packages/SettingsLib/res/values-ne/strings.xml +++ b/packages/SettingsLib/res/values-ne/strings.xml @@ -154,6 +154,8 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"छवि सम्बन्धी"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"हेडफोन"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"इनपुट सम्बन्धी बाह्य यन्त्र"</string> + <!-- no translation found for bluetooth_talkback_hearing_aids (3983279945542595479) --> + <skip /> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"ब्लुटुथ"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wi-Fi बन्द।"</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wi-Fi जडान विच्छेद भयो।"</string> @@ -455,6 +457,10 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"तपाईं रङ सच्याउने सुविधाका सहायताले निम्न कार्य गर्न सक्नुहुन्छ:<br/> <ol> <li>&nbsp;अझ सटीक तरिकाले रङहरू हेर्न</li> <li>&nbsp;फोकस गर्नका लागि रङहरू हटाउन</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> द्वारा अधिरोहित"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_on_hold_settings_home_page (7690464049464805856) --> + <skip /> + <!-- no translation found for power_incompatible_charging_settings_home_page (1261756225093962684) --> + <skip /> <string name="power_remaining_duration_only" msgid="8264199158671531431">"लगभग <xliff:g id="TIME_REMAINING">%1$s</xliff:g> बाँकी छ"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"लगभग <xliff:g id="TIME_REMAINING">%1$s</xliff:g> बाँकी छ (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"तपाईंको प्रयोगको आधारमा लगभग <xliff:g id="TIME_REMAINING">%1$s</xliff:g> बाँकी छ"</string> @@ -483,9 +489,12 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"वायरलेस तरिकाले चार्ज गरिँदै छ"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"चार्ज हुँदै छ"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"चार्ज भइरहेको छैन"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"कनेक्ट गरिएको छ, चार्ज भइरहेको छैन"</string> + <!-- no translation found for battery_info_status_not_charging (1103084691314264664) --> + <skip /> <string name="battery_info_status_full" msgid="1339002294876531312">"चार्ज भयो"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"पूर्ण रूपमा चार्ज भएको छ"</string> + <!-- no translation found for battery_info_status_charging_on_hold (6364355145521694438) --> + <skip /> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"प्रशासकद्वारा नियन्त्रित"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"प्रतिबन्धित सेटिङले नियन्त्रण गरेको"</string> <string name="disabled" msgid="8017887509554714950">"असक्षम पारियो"</string> diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml index a65ff730dc8c..f5767229a332 100644 --- a/packages/SettingsLib/res/values-nl/strings.xml +++ b/packages/SettingsLib/res/values-nl/strings.xml @@ -154,6 +154,7 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Replicatieapparaat"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Hoofdtelefoon"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Randapparaat voor invoer"</string> + <string name="bluetooth_talkback_hearing_aids" msgid="3983279945542595479">"Hoortoestellen"</string> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wifi staat uit."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wifi-verbinding verbroken."</string> @@ -455,6 +456,8 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Kleurcorrectie kan handig zijn in de volgende situaties:<br/> <ol> <li>&nbsp;Je wilt kleuren nauwkeuriger zien.</li> <li>&nbsp;Je wilt kleuren verwijderen zodat je je beter kunt focussen.</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Overschreven door <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <string name="power_charging_on_hold_settings_home_page" msgid="7690464049464805856">"<xliff:g id="LEVEL">%1$s</xliff:g>: opladen is in de wacht gezet om de batterij te beschermen"</string> + <string name="power_incompatible_charging_settings_home_page" msgid="1261756225093962684">"<xliff:g id="LEVEL">%1$s</xliff:g>: oplaadaccessoire checken"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Nog ongeveer <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"Nog ongeveer <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"Nog ongeveer <xliff:g id="TIME_REMAINING">%1$s</xliff:g> op basis van je gebruik"</string> @@ -483,9 +486,10 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Draadloos opladen"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Opladen"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"Wordt niet opgeladen"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Verbonden, wordt niet opgeladen"</string> + <string name="battery_info_status_not_charging" msgid="1103084691314264664">"Verbonden, maar wordt niet opgeladen"</string> <string name="battery_info_status_full" msgid="1339002294876531312">"Opgeladen"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Volledig opgeladen"</string> + <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Opladen in de wacht"</string> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Ingesteld door beheerder"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Beheerd door beperkte instelling"</string> <string name="disabled" msgid="8017887509554714950">"Uitgezet"</string> diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml index add9ff708d5e..ea245c4812b1 100644 --- a/packages/SettingsLib/res/values-or/strings.xml +++ b/packages/SettingsLib/res/values-or/strings.xml @@ -154,6 +154,8 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"ଇମେଜିଙ୍ଗ"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"ହେଡ୍ଫୋନ୍"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"ଇନ୍ପୁଟ୍ ଉପକରଣ"</string> + <!-- no translation found for bluetooth_talkback_hearing_aids (3983279945542595479) --> + <skip /> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"ବ୍ଲୁଟୁଥ"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"ୱାଇ-ଫାଇ ବନ୍ଦ।"</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"ୱାଇଫାଇ ବିଚ୍ଛିନ୍ନ କରାଗଲା।"</string> @@ -455,6 +457,10 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"ଆପଣ ଏସବୁ କରିବାକୁ ଚାହିଁଲେ ରଙ୍ଗ ସଂଶୋଧନ ଉପଯୋଗୀ ହୋଇପାରିବ:<br/> <ol> <li>&nbsp;ଆହୁରି ସଠିକ୍ ଭାବେ ରଙ୍ଗଗୁଡ଼ିକ ଦେଖିବା</li> <li>&nbsp;ଆପଣଙ୍କୁ ଫୋକସ କରିବାରେ ସାହାଯ୍ୟ କରିବା ପାଇଁ ରଙ୍ଗଗୁଡ଼ିକୁ କାଢ଼ିବା</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> ଦ୍ୱାରା ଓଭର୍ରାଇଡ୍ କରାଯାଇଛି"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_on_hold_settings_home_page (7690464049464805856) --> + <skip /> + <!-- no translation found for power_incompatible_charging_settings_home_page (1261756225093962684) --> + <skip /> <string name="power_remaining_duration_only" msgid="8264199158671531431">"ପାଖାପାଖି <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ବଳକା ଅଛି"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"ପାଖାପାଖି <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ପାଇଁ (<xliff:g id="LEVEL">%2$s</xliff:g>) ବଳକା ଅଛି"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"ଆପଣଙ୍କ ବ୍ୟବହାରକୁ ଆଧାର କରି ପାଖାପାଖି <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ବଳକା ଅଛି"</string> @@ -483,9 +489,12 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"ୱେୟରଲେସ ଭାବେ ଚାର୍ଜିଂ"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"ଚାର୍ଜ ହେଉଛି"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"ଚାର୍ଜ ହେଉନାହିଁ"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"ସଂଯୋଗ କରାଯାଇଛି, ଚାର୍ଜ ହେଉନାହିଁ"</string> + <!-- no translation found for battery_info_status_not_charging (1103084691314264664) --> + <skip /> <string name="battery_info_status_full" msgid="1339002294876531312">"ଚାର୍ଜ ହୋଇଯାଇଛି"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"ସମ୍ପୂର୍ଣ୍ଣ ଭାବରେ ଚାର୍ଜ ହୋଇଛି"</string> + <!-- no translation found for battery_info_status_charging_on_hold (6364355145521694438) --> + <skip /> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"ଆଡ୍ମିନ୍ ଦ୍ୱାରା ନିୟନ୍ତ୍ରିତ"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"ପ୍ରତିବନ୍ଧିତ ସେଟିଂ ଦ୍ୱାରା ନିୟନ୍ତ୍ରଣ କରାଯାଇଛି"</string> <string name="disabled" msgid="8017887509554714950">"ଅକ୍ଷମ ହୋଇଛି"</string> diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml index 42d47f645f8b..47c0f8abdbb5 100644 --- a/packages/SettingsLib/res/values-pa/strings.xml +++ b/packages/SettingsLib/res/values-pa/strings.xml @@ -154,6 +154,8 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"ਇਮੇਜਿੰਗ"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"ਹੈੱਡਫੋਨ"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"ਇਨਪੁੱਟ ਪੈਰਿਫੈਰਲ"</string> + <!-- no translation found for bluetooth_talkback_hearing_aids (3983279945542595479) --> + <skip /> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"ਬਲੂਟੁੱਥ"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wifi ਬੰਦ।"</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wifi ਡਿਸਕਨੈਕਟ ਕੀਤਾ।"</string> @@ -455,6 +457,10 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"ਰੰਗ ਸੁਧਾਈ ਉਦੋਂ ਲਾਹੇਵੰਦ ਹੋ ਸਕਦੀ ਹੈ, ਜਦੋਂ ਤੁਸੀਂ:<br/> <ol> <li>&nbsp;ਰੰਗਾਂ ਨੂੰ ਹੋਰ ਸਹੀ ਢੰਗ ਨਾਲ ਦੇਖਣਾ ਚਾਹੋ</li> <li>&nbsp;ਫੋਕਸ ਕਰਨ ਵਿੱਚ ਮਦਦ ਲਈ ਰੰਗ ਹਟਾਉਣਾ ਚਾਹੋ</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> ਦੁਆਰਾ ਓਵਰਰਾਈਡ ਕੀਤਾ"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_on_hold_settings_home_page (7690464049464805856) --> + <skip /> + <!-- no translation found for power_incompatible_charging_settings_home_page (1261756225093962684) --> + <skip /> <string name="power_remaining_duration_only" msgid="8264199158671531431">"ਲਗਭਗ <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ਬਾਕੀ"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"ਲਗਭਗ <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ਬਾਕੀ (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"ਤੁਹਾਡੀ ਵਰਤੋਂ ਦੇ ਆਧਾਰ \'ਤੇ ਲਗਭਗ <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ਬਾਕੀ"</string> @@ -483,9 +489,12 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"ਬਿਨਾਂ ਤਾਰ ਤੋਂ ਚਾਰਜ ਹੋ ਰਹੀ ਹੈ"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"ਚਾਰਜ ਨਹੀਂ ਹੋ ਰਿਹਾ"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"ਕਨੈਕਟ ਹੈ, ਚਾਰਜ ਨਹੀਂ ਹੋ ਰਹੀ"</string> + <!-- no translation found for battery_info_status_not_charging (1103084691314264664) --> + <skip /> <string name="battery_info_status_full" msgid="1339002294876531312">"ਚਾਰਜ ਹੋ ਗਈ"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"ਪੂਰੀ ਚਾਰਜ ਹੋ ਗਈ ਹੈ"</string> + <!-- no translation found for battery_info_status_charging_on_hold (6364355145521694438) --> + <skip /> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"ਪ੍ਰਸ਼ਾਸਕ ਵੱਲੋਂ ਕੰਟਰੋਲ ਕੀਤੀ ਗਈ"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"ਪ੍ਰਤਿਬੰਧਿਤ ਸੈਟਿੰਗ ਰਾਹੀਂ ਕੰਟਰੋਲ ਕੀਤੀ ਜਾਂਦੀ ਹੈ"</string> <string name="disabled" msgid="8017887509554714950">"ਅਯੋਗ ਬਣਾਇਆ"</string> diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml index b319cab8395a..a8ba18d59ab2 100644 --- a/packages/SettingsLib/res/values-pl/strings.xml +++ b/packages/SettingsLib/res/values-pl/strings.xml @@ -154,6 +154,8 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Obrazowanie"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Słuchawki"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Peryferyjne urządzenie wejściowe"</string> + <!-- no translation found for bluetooth_talkback_hearing_aids (3983279945542595479) --> + <skip /> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wi-Fi wyłączone."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wi-Fi odłączone."</string> @@ -455,6 +457,10 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Korekcja kolorów może być pomocna, gdy:<br/> <ol> <li>&nbsp;chcesz wyraźniej widzieć kolory;</li> <li>&nbsp;chcesz usunąć kolory, aby łatwiej było się skupić.</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Nadpisana przez <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_on_hold_settings_home_page (7690464049464805856) --> + <skip /> + <!-- no translation found for power_incompatible_charging_settings_home_page (1261756225093962684) --> + <skip /> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Jeszcze około <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"Jeszcze około <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"Jeszcze około <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (na podstawie Twojego sposobu korzystania)"</string> @@ -483,9 +489,12 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Ładowanie bezprzewodowe"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Ładowanie"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"Nie podłączony"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Podłączono, brak ładowania"</string> + <!-- no translation found for battery_info_status_not_charging (1103084691314264664) --> + <skip /> <string name="battery_info_status_full" msgid="1339002294876531312">"Naładowana"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Bateria w pełni naładowana"</string> + <!-- no translation found for battery_info_status_charging_on_hold (6364355145521694438) --> + <skip /> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Kontrolowane przez administratora"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Kontrolowane przez ograniczone ustawienia"</string> <string name="disabled" msgid="8017887509554714950">"Wyłączone"</string> diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml index 32fa1b621e01..814215e90fdb 100644 --- a/packages/SettingsLib/res/values-pt-rBR/strings.xml +++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml @@ -154,6 +154,7 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Imagem"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Headphone"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Periférico de entrada"</string> + <string name="bluetooth_talkback_hearing_aids" msgid="3983279945542595479">"Aparelhos auditivos"</string> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wi-Fi desligado."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wi-Fi desconectado"</string> @@ -455,6 +456,8 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"A correção de cor pode ser útil caso você queira:<br/> <ol> <li>&nbsp;ver cores mais nítidas;</li> <li>&nbsp;remover cores para que você possa se concentrar.</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Substituído por <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <string name="power_charging_on_hold_settings_home_page" msgid="7690464049464805856">"<xliff:g id="LEVEL">%1$s</xliff:g> - Carregamento suspenso para proteger a bateria"</string> + <string name="power_incompatible_charging_settings_home_page" msgid="1261756225093962684">"<xliff:g id="LEVEL">%1$s</xliff:g> - Verificando o acessório de carregamento"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Tempo restante aproximado: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"Tempo restante aproximado: <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"Tempo restante aproximado, com base no seu uso: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -483,9 +486,10 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Carregando sem fio"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Carregando"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"Não está carregando"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Conectado sem carregar"</string> + <string name="battery_info_status_not_charging" msgid="1103084691314264664">"Conectado, mas não está carregando"</string> <string name="battery_info_status_full" msgid="1339002294876531312">"Carregada"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Carga completa"</string> + <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Carregamento suspenso"</string> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Controlada pelo admin"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Controlada pelas configurações restritas"</string> <string name="disabled" msgid="8017887509554714950">"Desativado"</string> diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml index 1a81f2dd8576..1d7b6094938e 100644 --- a/packages/SettingsLib/res/values-pt-rPT/strings.xml +++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml @@ -154,6 +154,7 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Dispositivo de imagem"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Auricular"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Periférico de entrada"</string> + <string name="bluetooth_talkback_hearing_aids" msgid="3983279945542595479">"Aparelhos auditivos"</string> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wi-Fi desativado."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wi-Fi desligado."</string> @@ -455,6 +456,8 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"A correção da cor pode ser útil quando quiser:<br/> <ol> <li>&nbsp;Ver cores com maior precisão</li> <li>&nbsp;Remover cores para ajudar a concentrar-se</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Substituído por <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <string name="power_charging_on_hold_settings_home_page" msgid="7690464049464805856">"<xliff:g id="LEVEL">%1$s</xliff:g> - Carregamento em espera para proteger a bateria"</string> + <string name="power_incompatible_charging_settings_home_page" msgid="1261756225093962684">"<xliff:g id="LEVEL">%1$s</xliff:g> – A verificar o acessório de carregamento"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Resta(m) cerca de <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"Resta(m) cerca de <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"Resta(m) cerca de <xliff:g id="TIME_REMAINING">%1$s</xliff:g> com base na sua utilização"</string> @@ -483,9 +486,10 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"A carregar sem fios"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"A carregar"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"Não está a carregar"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Ligado, não está a carregar"</string> + <string name="battery_info_status_not_charging" msgid="1103084691314264664">"Ligado, mas não está a carregar"</string> <string name="battery_info_status_full" msgid="1339002294876531312">"Carregada"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Totalmente carregada"</string> + <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Carregamento em espera"</string> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Controlado pelo gestor"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Controlado por uma definição restrita"</string> <string name="disabled" msgid="8017887509554714950">"Desativada"</string> diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml index 32fa1b621e01..814215e90fdb 100644 --- a/packages/SettingsLib/res/values-pt/strings.xml +++ b/packages/SettingsLib/res/values-pt/strings.xml @@ -154,6 +154,7 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Imagem"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Headphone"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Periférico de entrada"</string> + <string name="bluetooth_talkback_hearing_aids" msgid="3983279945542595479">"Aparelhos auditivos"</string> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wi-Fi desligado."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wi-Fi desconectado"</string> @@ -455,6 +456,8 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"A correção de cor pode ser útil caso você queira:<br/> <ol> <li>&nbsp;ver cores mais nítidas;</li> <li>&nbsp;remover cores para que você possa se concentrar.</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Substituído por <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <string name="power_charging_on_hold_settings_home_page" msgid="7690464049464805856">"<xliff:g id="LEVEL">%1$s</xliff:g> - Carregamento suspenso para proteger a bateria"</string> + <string name="power_incompatible_charging_settings_home_page" msgid="1261756225093962684">"<xliff:g id="LEVEL">%1$s</xliff:g> - Verificando o acessório de carregamento"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Tempo restante aproximado: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"Tempo restante aproximado: <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"Tempo restante aproximado, com base no seu uso: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -483,9 +486,10 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Carregando sem fio"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Carregando"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"Não está carregando"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Conectado sem carregar"</string> + <string name="battery_info_status_not_charging" msgid="1103084691314264664">"Conectado, mas não está carregando"</string> <string name="battery_info_status_full" msgid="1339002294876531312">"Carregada"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Carga completa"</string> + <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Carregamento suspenso"</string> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Controlada pelo admin"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Controlada pelas configurações restritas"</string> <string name="disabled" msgid="8017887509554714950">"Desativado"</string> diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml index 5956d635c68d..fef4378d5b0f 100644 --- a/packages/SettingsLib/res/values-ro/strings.xml +++ b/packages/SettingsLib/res/values-ro/strings.xml @@ -154,6 +154,8 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Dispozitiv pentru imagini"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Căști"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Dispozitiv periferic de intrare"</string> + <!-- no translation found for bluetooth_talkback_hearing_aids (3983279945542595479) --> + <skip /> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wi-Fi dezactivat."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wi-Fi deconectat."</string> @@ -455,6 +457,10 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Corecția culorii poate fi utilă dacă vrei:<br/> <ol> <li>&nbsp;să vezi mai precis culorile;</li> <li>&nbsp;să elimini culorile pentru a te concentra mai bine.</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Valoare înlocuită de <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_on_hold_settings_home_page (7690464049464805856) --> + <skip /> + <!-- no translation found for power_incompatible_charging_settings_home_page (1261756225093962684) --> + <skip /> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Timp aproximativ rămas: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"Timp aproximativ rămas: <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"În baza utilizării, timpul rămas este de aproximativ <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -483,9 +489,12 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Se încarcă wireless"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Se încarcă"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"Nu se încarcă"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Conectat, nu se încarcă"</string> + <!-- no translation found for battery_info_status_not_charging (1103084691314264664) --> + <skip /> <string name="battery_info_status_full" msgid="1339002294876531312">"Încărcată"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Complet încărcată"</string> + <!-- no translation found for battery_info_status_charging_on_hold (6364355145521694438) --> + <skip /> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Controlată de administrator"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Controlată de setarea restricționată"</string> <string name="disabled" msgid="8017887509554714950">"Dezactivată"</string> diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml index fe65be5114b0..5989e2a1a392 100644 --- a/packages/SettingsLib/res/values-ru/strings.xml +++ b/packages/SettingsLib/res/values-ru/strings.xml @@ -154,6 +154,8 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Камера"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Наушники"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Периферийное устройство ввода"</string> + <!-- no translation found for bluetooth_talkback_hearing_aids (3983279945542595479) --> + <skip /> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wi-Fi выключен"</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wi-Fi отключен"</string> @@ -455,6 +457,10 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Используйте коррекцию цвета, чтобы:<br/> <ol> <li> Добиться нужной цветопередачи.</li> <li> Убрать цвета, которые мешают сосредоточиться.</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Новая настройка: <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"Уровень заряда – <xliff:g id="PERCENTAGE">%1$s</xliff:g>. <xliff:g id="TIME_STRING">%2$s</xliff:g>."</string> + <!-- no translation found for power_charging_on_hold_settings_home_page (7690464049464805856) --> + <skip /> + <!-- no translation found for power_incompatible_charging_settings_home_page (1261756225093962684) --> + <skip /> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Заряда хватит примерно на <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"Заряда (<xliff:g id="LEVEL">%2$s</xliff:g>) хватит примерно на <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"Заряда хватит примерно на <xliff:g id="TIME_REMAINING">%1$s</xliff:g> при текущем уровне расхода"</string> @@ -483,9 +489,12 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Беспроводная зарядка"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Зарядка"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"Не заряжается"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Подключено, не заряжается"</string> + <!-- no translation found for battery_info_status_not_charging (1103084691314264664) --> + <skip /> <string name="battery_info_status_full" msgid="1339002294876531312">"Батарея заряжена"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Батарея заряжена"</string> + <!-- no translation found for battery_info_status_charging_on_hold (6364355145521694438) --> + <skip /> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Контролируется администратором"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Контролируется настройками с ограниченным доступом"</string> <string name="disabled" msgid="8017887509554714950">"Отключено"</string> diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml index 55e0778662ea..5c3243b401d9 100644 --- a/packages/SettingsLib/res/values-si/strings.xml +++ b/packages/SettingsLib/res/values-si/strings.xml @@ -154,6 +154,8 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"නිරූපණය"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"හෙඩ්ෆෝන්"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"ආදාන උපාංග"</string> + <!-- no translation found for bluetooth_talkback_hearing_aids (3983279945542595479) --> + <skip /> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"බ්ලූටූත්"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wifi අක්රියයි."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wifi සම්බන්ධ කර නොමැත."</string> @@ -455,6 +457,10 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"ඔබට පහත දේවල් සිදු කිරීම අවශ්ය විට වර්ණ නිවැරදි කිරීම ප්රයෝජනවත් විය හැකිය:<br/> <ol> <li>වඩාත් නිවැරදිව වර්ණ දැකීම</li> <li>ඔබට අවධානය යොමු කිරීමට උදවු වීමට වර්ණ ඉවත් කිරීම</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> මගින් ඉක්මවන ලදී"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_on_hold_settings_home_page (7690464049464805856) --> + <skip /> + <!-- no translation found for power_incompatible_charging_settings_home_page (1261756225093962684) --> + <skip /> <string name="power_remaining_duration_only" msgid="8264199158671531431">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> ක් පමණ ඉතිරියි"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> ක් පමණ ඉතිරියි (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"ඔබේ භාවිතය මත පදනම්ව <xliff:g id="TIME_REMAINING">%1$s</xliff:g> පමණ ඉතිරිව ඇත"</string> @@ -483,9 +489,12 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"නොරැහැන්ව ආරෝපණය වේ"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"ආරෝපණය වේ"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"ආරෝපණය නොවේ"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"සම්බන්ධයි, ආරෝපණය නොවේ"</string> + <!-- no translation found for battery_info_status_not_charging (1103084691314264664) --> + <skip /> <string name="battery_info_status_full" msgid="1339002294876531312">"අරෝපිතයි"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"සම්පූර්ණයෙන් ආරෝපණ වී ඇත"</string> + <!-- no translation found for battery_info_status_charging_on_hold (6364355145521694438) --> + <skip /> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"පරිපාලක විසින් පාලනය කරන ලදී"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"සීමා කළ සැකසීම මගින් පාලනය වේ"</string> <string name="disabled" msgid="8017887509554714950">"අබල කර ඇත"</string> diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml index 4d03ddd79201..a9b518d5018e 100644 --- a/packages/SettingsLib/res/values-sk/strings.xml +++ b/packages/SettingsLib/res/values-sk/strings.xml @@ -154,6 +154,7 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Snímkovacie zariadenie"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Slúchadlá"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Periférne vstupné zariadenie"</string> + <string name="bluetooth_talkback_hearing_aids" msgid="3983279945542595479">"Načúvadlá"</string> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Sieť Wi‑Fi je vypnutá."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Sieť Wi‑Fi je odpojená."</string> @@ -455,6 +456,8 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Úprava farieb môže byť užitočná, keď chcete:<br/> <ol> <li>&nbsp;zobrazovať farby presnejšie;</li> <li>&nbsp;odstrániť farby, aby ste sa mohli sústrediť.</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Prekonané predvoľbou <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <string name="power_charging_on_hold_settings_home_page" msgid="7690464049464805856">"<xliff:g id="LEVEL">%1$s</xliff:g> – nabíjanie je pozastavené, aby sa chránila batéria"</string> + <string name="power_incompatible_charging_settings_home_page" msgid="1261756225093962684">"<xliff:g id="LEVEL">%1$s</xliff:g> – kontroluje sa nabíjacie príslušenstvo"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Ešte približne <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"Zostáva približne <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"Zostáva približne <xliff:g id="TIME_REMAINING">%1$s</xliff:g> – závisí to od intenzity využitia"</string> @@ -483,9 +486,10 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Nabíja sa bezdrôtovo"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Nabíja sa"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"Nenabíja sa"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Pripojené, nenabíja sa"</string> + <string name="battery_info_status_not_charging" msgid="1103084691314264664">"Pripojené, ale nenabíja sa"</string> <string name="battery_info_status_full" msgid="1339002294876531312">"Nabité"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Úplne nabitá"</string> + <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Nabíjanie je pozastavené"</string> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Ovládané správcom"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Ovládané obmedzeným nastavením"</string> <string name="disabled" msgid="8017887509554714950">"Deaktivované"</string> diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml index ddf0f710f0b2..f739fbe0a7f8 100644 --- a/packages/SettingsLib/res/values-sl/strings.xml +++ b/packages/SettingsLib/res/values-sl/strings.xml @@ -154,6 +154,7 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Naprava za zajem slik"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Slušalka"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Zunanja dodatna oprema"</string> + <string name="bluetooth_talkback_hearing_aids" msgid="3983279945542595479">"Slušni aparati"</string> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wi-Fi je izklopljen."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Povezava Wi-Fi je prekinjena."</string> @@ -455,6 +456,8 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Popravljanje barv je lahko koristno, ko želite:<br/> <ol> <li>&nbsp;natančneje videti barve;</li> <li>&nbsp;odstraniti barve, da se lažje osredotočite.</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Preglasila nastavitev: <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <string name="power_charging_on_hold_settings_home_page" msgid="7690464049464805856">"<xliff:g id="LEVEL">%1$s</xliff:g> – Zaradi zaščite baterije je polnjenje na čakanju"</string> + <string name="power_incompatible_charging_settings_home_page" msgid="1261756225093962684">"<xliff:g id="LEVEL">%1$s</xliff:g> – Preverjanje pripomočka za polnjenje"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Še približno <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"Še približno <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"Glede na način uporabe še približno <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -483,9 +486,10 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Brezžično polnjenje"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Polnjenje"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"Se ne polni"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Povezano, se ne polni"</string> + <string name="battery_info_status_not_charging" msgid="1103084691314264664">"Naprava je povezana, vendar se ne polni"</string> <string name="battery_info_status_full" msgid="1339002294876531312">"Napolnjeno"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Popolnoma napolnjena"</string> + <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Polnjenje je na čakanju"</string> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Nadzira skrbnik"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Pod nadzorom omejene nastavitve"</string> <string name="disabled" msgid="8017887509554714950">"Onemogočeno"</string> diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml index b627d097055b..d9fe7381e8b3 100644 --- a/packages/SettingsLib/res/values-sq/strings.xml +++ b/packages/SettingsLib/res/values-sq/strings.xml @@ -154,6 +154,8 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Imazhe"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Kufje"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Hyrje periferike"</string> + <!-- no translation found for bluetooth_talkback_hearing_aids (3983279945542595479) --> + <skip /> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth-i"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wi-Fi është çaktivizuar."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wi-Fi është i shkëputur."</string> @@ -455,6 +457,10 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Korrigjimi i ngjyrës mund të jetë i dobishëm kur dëshiron:<br/> <ol> <li>&nbsp;Të shohësh ngjyrat më saktë</li> <li>&nbsp;Të heqësh ngjyrat për të të ndihmuar të fokusohesh</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Mbivendosur nga <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_on_hold_settings_home_page (7690464049464805856) --> + <skip /> + <!-- no translation found for power_incompatible_charging_settings_home_page (1261756225093962684) --> + <skip /> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Rreth <xliff:g id="TIME_REMAINING">%1$s</xliff:g> të mbetura"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"Rreth <xliff:g id="TIME_REMAINING">%1$s</xliff:g> të mbetura (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"Rreth <xliff:g id="TIME_REMAINING">%1$s</xliff:g> të mbetura bazuar në përdorimin tënd"</string> @@ -483,9 +489,12 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Po karikohet wireless"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Po karikohet"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"Nuk po karikohet"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Lidhur, jo në karikim"</string> + <!-- no translation found for battery_info_status_not_charging (1103084691314264664) --> + <skip /> <string name="battery_info_status_full" msgid="1339002294876531312">"Karikuar"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Karikuar plotësisht"</string> + <!-- no translation found for battery_info_status_charging_on_hold (6364355145521694438) --> + <skip /> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Kontrolluar nga administratori"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Kontrollohet nga \"Cilësimet e kufizuara\""</string> <string name="disabled" msgid="8017887509554714950">"Çaktivizuar"</string> diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml index 224be52fb23d..042fc34b0791 100644 --- a/packages/SettingsLib/res/values-sr/strings.xml +++ b/packages/SettingsLib/res/values-sr/strings.xml @@ -154,6 +154,8 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Обрада слика"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Слушалице"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Периферни уређај за унос"</string> + <!-- no translation found for bluetooth_talkback_hearing_aids (3983279945542595479) --> + <skip /> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"WiFi је искључен."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"WiFi веза је прекинута."</string> @@ -455,6 +457,10 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Корекција боја може да буде корисна када желите:<br/> <ol> <li>&nbsp;Прецизније да видите боје</li> <li>&nbsp;Да уклоните боје како бисте се фокусирали</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Замењује га <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g>–<xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_on_hold_settings_home_page (7690464049464805856) --> + <skip /> + <!-- no translation found for power_incompatible_charging_settings_home_page (1261756225093962684) --> + <skip /> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Преостало је око <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"Преостало је око <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"Преостало је око <xliff:g id="TIME_REMAINING">%1$s</xliff:g> на основу коришћења"</string> @@ -483,9 +489,12 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Бежично пуњење"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Пуњење"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"Не пуни се"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Повезано, не пуни се"</string> + <!-- no translation found for battery_info_status_not_charging (1103084691314264664) --> + <skip /> <string name="battery_info_status_full" msgid="1339002294876531312">"Напуњено"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Напуњено до краја"</string> + <!-- no translation found for battery_info_status_charging_on_hold (6364355145521694438) --> + <skip /> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Контролише администратор"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Контролишу ограничена подешавања"</string> <string name="disabled" msgid="8017887509554714950">"Онемогућено"</string> diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml index 7ffad7c387b7..1f103e8adeaf 100644 --- a/packages/SettingsLib/res/values-sv/strings.xml +++ b/packages/SettingsLib/res/values-sv/strings.xml @@ -154,6 +154,8 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Bild"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Hörlur"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Inmatning från kringutrustning"</string> + <!-- no translation found for bluetooth_talkback_hearing_aids (3983279945542595479) --> + <skip /> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wifi är inaktiverat."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Ingen wifi-anslutning."</string> @@ -455,6 +457,10 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Färgkorrigering kan vara bra för att<br/> <ol> <li>&nbsp;urskilja färger bättre</li> <li>&nbsp;ta bort färger som distraherar</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Har åsidosatts av <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_on_hold_settings_home_page (7690464049464805856) --> + <skip /> + <!-- no translation found for power_incompatible_charging_settings_home_page (1261756225093962684) --> + <skip /> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Cirka <xliff:g id="TIME_REMAINING">%1$s</xliff:g> kvar"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"Cirka <xliff:g id="TIME_REMAINING">%1$s</xliff:g> kvar (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"Cirka <xliff:g id="TIME_REMAINING">%1$s</xliff:g> kvar utifrån din användning"</string> @@ -483,9 +489,12 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Laddas trådlöst"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Laddas"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"Laddar inte"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Ansluten, laddas inte"</string> + <!-- no translation found for battery_info_status_not_charging (1103084691314264664) --> + <skip /> <string name="battery_info_status_full" msgid="1339002294876531312">"Laddat"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Fulladdad"</string> + <!-- no translation found for battery_info_status_charging_on_hold (6364355145521694438) --> + <skip /> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Strys av administratören"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Styrs av spärrad inställning"</string> <string name="disabled" msgid="8017887509554714950">"Inaktiverad"</string> diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml index a94c313ee817..0d1ef461e57b 100644 --- a/packages/SettingsLib/res/values-sw/strings.xml +++ b/packages/SettingsLib/res/values-sw/strings.xml @@ -154,6 +154,7 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Kupiga picha"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Kifaa cha sauti"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Vifaa vya Ziada vya Kuingiza Data"</string> + <string name="bluetooth_talkback_hearing_aids" msgid="3983279945542595479">"Visaidizi vya Kusikia"</string> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wifi imezimwa."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wifi imeondolewa."</string> @@ -455,6 +456,8 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Usahihishaji wa rangi unaweza kusaidia wakati unataka:<br/> <ol> <li>&nbsp;Kuona rangi kwa usahihi zaidi</li> <li>&nbsp;Kuondoa rangi ili ikusaidie kumakinika</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Imetanguliwa na <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <string name="power_charging_on_hold_settings_home_page" msgid="7690464049464805856">"<xliff:g id="LEVEL">%1$s</xliff:g> - Imesitisha kuchaji ili kulinda betri yako"</string> + <string name="power_incompatible_charging_settings_home_page" msgid="1261756225093962684">"<xliff:g id="LEVEL">%1$s</xliff:g> - Inakagua kifaa cha kuchaji"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Zimesalia takribani <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"Zimesalia takribani <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"Zimesalia takribani <xliff:g id="TIME_REMAINING">%1$s</xliff:g> kulingana na jinsi unavyoitumia"</string> @@ -483,9 +486,10 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Inachaji bila kutumia waya"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Inachaji"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"Haichaji"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Imeunganishwa, haichaji"</string> + <string name="battery_info_status_not_charging" msgid="1103084691314264664">"Imeunganishwa, lakini haichaji"</string> <string name="battery_info_status_full" msgid="1339002294876531312">"Imechajiwa"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Imejaa Chaji"</string> + <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Imesitisha kuchaji"</string> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Imedhibitiwa na msimamizi"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Imedhibitiwa na Mpangilio wenye Mipaka"</string> <string name="disabled" msgid="8017887509554714950">"Imezimwa"</string> diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml index b76f7e34fbb7..21e7bf3b9fd6 100644 --- a/packages/SettingsLib/res/values-ta/strings.xml +++ b/packages/SettingsLib/res/values-ta/strings.xml @@ -154,6 +154,8 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"இமேஜிங்"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"ஹெட்ஃபோன்"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"இன்புட் பெரிபெரல்"</string> + <!-- no translation found for bluetooth_talkback_hearing_aids (3983279945542595479) --> + <skip /> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"புளூடூத்"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"வைஃபை முடக்கப்பட்டது."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"வைஃபை துண்டிக்கப்பட்டது."</string> @@ -455,6 +457,10 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"நீங்கள் இவற்றைச் செய்ய விரும்பும்போது கலர் கரெக்ஷன் உதவும்:<br/> <ol> <li>&nbsp;வண்ணங்களை மிகத் துல்லியமாகப் பார்த்தல்</li> <li>&nbsp;கவனம் செலுத்துவதற்கு உதவ வண்ணங்களை அகற்றுதல்</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> மூலம் மேலெழுதப்பட்டது"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_on_hold_settings_home_page (7690464049464805856) --> + <skip /> + <!-- no translation found for power_incompatible_charging_settings_home_page (1261756225093962684) --> + <skip /> <string name="power_remaining_duration_only" msgid="8264199158671531431">"கிட்டத்தட்ட <xliff:g id="TIME_REMAINING">%1$s</xliff:g> மீதமுள்ளது"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"கிட்டத்தட்ட <xliff:g id="TIME_REMAINING">%1$s</xliff:g> மீதமுள்ளது (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"உபயோகத்தின் அடிப்படையில் கிட்டத்தட்ட <xliff:g id="TIME_REMAINING">%1$s</xliff:g> மீதமுள்ளது"</string> @@ -483,9 +489,12 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"வயரின்றி சார்ஜாகிறது"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"சார்ஜாகிறது"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"சார்ஜ் செய்யப்படவில்லை"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"இணைக்கப்பட்டுள்ளது, சார்ஜாகவில்லை"</string> + <!-- no translation found for battery_info_status_not_charging (1103084691314264664) --> + <skip /> <string name="battery_info_status_full" msgid="1339002294876531312">"சார்ஜாகிவிட்டது"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"முழுவதும் சார்ஜாகிவிட்டது"</string> + <!-- no translation found for battery_info_status_charging_on_hold (6364355145521694438) --> + <skip /> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"நிர்வாகி கட்டுப்படுத்துகிறார்"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"வரையறுக்கப்பட்ட அமைப்பால் கட்டுப்படுத்தப்படுகிறது"</string> <string name="disabled" msgid="8017887509554714950">"முடக்கப்பட்டது"</string> diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml index 23c00c11e866..ce432b6e72c2 100644 --- a/packages/SettingsLib/res/values-te/strings.xml +++ b/packages/SettingsLib/res/values-te/strings.xml @@ -154,6 +154,7 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"ప్రతిబింబనం"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"హెడ్ఫోన్"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"ఇన్పుట్ అనుబంధ పరికరం"</string> + <string name="bluetooth_talkback_hearing_aids" msgid="3983279945542595479">"వినికిడి పరికరాలు"</string> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"బ్లూటూత్"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wifi ఆఫ్లో ఉంది."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wifi డిస్కనెక్ట్ చేయబడింది."</string> @@ -455,6 +456,8 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"మీరు కింది వాటిని చేయాలనుకున్నప్పుడు కలర్ కరెక్షన్ సహాయకరంగా ఉంటుంది:<br/> <ol> <li>&nbsp;రంగులను మరింత ఖచ్చితంగా చూసేందుకు సహాయపడుతుంది</li> <li>&nbsp;మీరు ఫోకస్ చేయడంలో సహాయపడటానికి రంగులను తీసివేయండి</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> ద్వారా భర్తీ చేయబడింది"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <string name="power_charging_on_hold_settings_home_page" msgid="7690464049464805856">"<xliff:g id="LEVEL">%1$s</xliff:g> - బ్యాటరీని రక్షించడానికి ఛార్జింగ్ హోల్డ్లో ఉంచబడింది"</string> + <string name="power_incompatible_charging_settings_home_page" msgid="1261756225093962684">"<xliff:g id="LEVEL">%1$s</xliff:g> - ఛార్జ్ చేసే పరికరాన్ని చెక్ చేయండి"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> సమయం మిగిలి ఉంది"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"దాదాపు <xliff:g id="TIME_REMAINING">%1$s</xliff:g> సమయం మిగిలి ఉంది (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"మీ వినియోగం ఆధారంగా దాదాపు <xliff:g id="TIME_REMAINING">%1$s</xliff:g> సమయం మిగిలి ఉంది"</string> @@ -483,9 +486,10 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"వైర్లెస్ ఛార్జింగ్"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"ఛార్జ్ అవుతోంది"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"ఛార్జ్ కావడం లేదు"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"కనెక్ట్ చేయబడింది, ఛార్జ్ చేయబడలేదు"</string> + <string name="battery_info_status_not_charging" msgid="1103084691314264664">"కనెక్ట్ అయి ఉంది, కానీ ఛార్జ్ అవ్వడం లేదు"</string> <string name="battery_info_status_full" msgid="1339002294876531312">"ఛార్జ్ చేయబడింది"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"పూర్తి ఛార్జ్ అయింది"</string> + <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"ఛార్జింగ్ హోల్డ్లో ఉంది"</string> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"నిర్వాహకుని ద్వారా నియంత్రించబడింది"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"పరిమితం చేసిన సెట్టింగ్ ద్వారా నియంత్రించబడుతుంది"</string> <string name="disabled" msgid="8017887509554714950">"డిజేబుల్ చేయబడింది"</string> diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml index 4d9d382c83ba..183130b53d9e 100644 --- a/packages/SettingsLib/res/values-th/strings.xml +++ b/packages/SettingsLib/res/values-th/strings.xml @@ -154,6 +154,7 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"การถ่ายภาพ"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"หูฟัง"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"อุปกรณ์อินพุต"</string> + <string name="bluetooth_talkback_hearing_aids" msgid="3983279945542595479">"เครื่องช่วยฟัง"</string> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"บลูทูธ"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wi-Fi ปิดอยู่"</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"ไม่ได้เชื่อมต่อ Wi-Fi"</string> @@ -455,6 +456,8 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"การแก้สีจะเป็นประโยชน์เมื่อคุณต้องการที่จะ<br/> <ol> <li>&nbsp;มองเห็นสีได้ถูกต้องยิ่งขึ้น</li> <li>&nbsp;นำสีออกเพื่อช่วยให้เห็นชัดเจนยิ่งขึ้น</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"แทนที่โดย <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <string name="power_charging_on_hold_settings_home_page" msgid="7690464049464805856">"<xliff:g id="LEVEL">%1$s</xliff:g> - หยุดการชาร์จชั่วคราวเพื่อถนอมแบตเตอรี่"</string> + <string name="power_incompatible_charging_settings_home_page" msgid="1261756225093962684">"<xliff:g id="LEVEL">%1$s</xliff:g> - กำลังตรวจสอบอุปกรณ์เสริมสำหรับการชาร์จ"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"เหลืออีกประมาณ <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"เหลืออีกประมาณ <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"เหลืออีกประมาณ <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ขึ้นอยู่กับการใช้งานของคุณ"</string> @@ -483,9 +486,10 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"กำลังชาร์จแบบไร้สาย"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"กำลังชาร์จ"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"ไม่ได้ชาร์จ"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"เชื่อมต่ออยู่ ไม่ได้ชาร์จ"</string> + <string name="battery_info_status_not_charging" msgid="1103084691314264664">"เชื่อมต่อแล้ว แต่ยังไม่ชาร์จ"</string> <string name="battery_info_status_full" msgid="1339002294876531312">"ชาร์จแล้ว"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"ชาร์จเต็มแล้ว"</string> + <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"หยุดการชาร์จชั่วคราว"</string> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"ผู้ดูแลระบบเป็นผู้ควบคุม"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"ควบคุมโดยการตั้งค่าที่จำกัด"</string> <string name="disabled" msgid="8017887509554714950">"ปิดอยู่"</string> diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml index c9e34941cfe1..f32a14a49dd9 100644 --- a/packages/SettingsLib/res/values-tl/strings.xml +++ b/packages/SettingsLib/res/values-tl/strings.xml @@ -154,6 +154,8 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Imaging"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Headphone"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Input Peripheral"</string> + <!-- no translation found for bluetooth_talkback_hearing_aids (3983279945542595479) --> + <skip /> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Naka-off ang Wifi."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Nakadiskonekta ang Wifi."</string> @@ -455,6 +457,10 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Puwedeng makatulong ang pagtatama ng kulay kapag gusto mong:<br/> <ol> <li>&nbsp;Makita nang mas tumpak ang mga kulay</li> <li>&nbsp;Alisin ang mga kulay para matulungan kang tumuon</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Na-override ng <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_on_hold_settings_home_page (7690464049464805856) --> + <skip /> + <!-- no translation found for power_incompatible_charging_settings_home_page (1261756225093962684) --> + <skip /> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Humigit-kumulang <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ang natitira"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"Humigit-kumulang <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ang natitira (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"Humigit-kumulang <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ang natitira batay sa iyong paggamit"</string> @@ -483,9 +489,12 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Wireless na nagcha-charge"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Nagcha-charge"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"Hindi nagcha-charge"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Nakakonekta, hindi nagcha-charge"</string> + <!-- no translation found for battery_info_status_not_charging (1103084691314264664) --> + <skip /> <string name="battery_info_status_full" msgid="1339002294876531312">"Charged"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Puno ang Baterya"</string> + <!-- no translation found for battery_info_status_charging_on_hold (6364355145521694438) --> + <skip /> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Pinapamahalaan ng admin"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Kinokontrol ng Pinaghihigpitang Setting"</string> <string name="disabled" msgid="8017887509554714950">"Naka-disable"</string> diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml index 0f628b44fe69..06e97291bf60 100644 --- a/packages/SettingsLib/res/values-tr/strings.xml +++ b/packages/SettingsLib/res/values-tr/strings.xml @@ -154,6 +154,8 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Görüntüleme"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Kulaklık"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Giriş Çevre Birimi"</string> + <!-- no translation found for bluetooth_talkback_hearing_aids (3983279945542595479) --> + <skip /> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Kablosuz kapalı."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Kablosuz bağlantı kesildi."</string> @@ -455,6 +457,10 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Renk düzeltme aşağıdaki durumlarda faydalı olabilir:<br/> <ol> <li>&nbsp;Renkleri daha doğru görmek istediğinizde</li> <li>&nbsp;Odaklanmak için renkleri kaldırmak istediğinizde</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> tarafından geçersiz kılındı"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_on_hold_settings_home_page (7690464049464805856) --> + <skip /> + <!-- no translation found for power_incompatible_charging_settings_home_page (1261756225093962684) --> + <skip /> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Yaklaşık <xliff:g id="TIME_REMAINING">%1$s</xliff:g> kaldı"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"Yaklaşık <xliff:g id="TIME_REMAINING">%1$s</xliff:g> kaldı (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"Kullanımınıza dayalı olarak yaklaşık <xliff:g id="TIME_REMAINING">%1$s</xliff:g> kaldı"</string> @@ -483,9 +489,12 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Kablosuz şarj oluyor"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Şarj Etme"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"Şarj olmuyor"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Bağlandı, şarj olmuyor"</string> + <!-- no translation found for battery_info_status_not_charging (1103084691314264664) --> + <skip /> <string name="battery_info_status_full" msgid="1339002294876531312">"Şarj oldu"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Pilin Şarjı Tam"</string> + <!-- no translation found for battery_info_status_charging_on_hold (6364355145521694438) --> + <skip /> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Yönetici tarafından denetleniyor"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Kısıtlanmış ayar tarafından kontrol ediliyor"</string> <string name="disabled" msgid="8017887509554714950">"Devre dışı"</string> diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml index e00fbc990461..cd00e172d5cc 100644 --- a/packages/SettingsLib/res/values-uk/strings.xml +++ b/packages/SettingsLib/res/values-uk/strings.xml @@ -154,6 +154,8 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Візуалізація"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Навушники"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Периферійне введення"</string> + <!-- no translation found for bluetooth_talkback_hearing_aids (3983279945542595479) --> + <skip /> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wi-Fi вимкнено."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wi-Fi від’єднано."</string> @@ -455,6 +457,10 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Корекція кольору корисна, якщо ви хочете:<br/> <ol> <li>&nbsp;точніше бачити кольори;</li> <li>&nbsp;вилучити кольори, щоб легше зосереджуватися.</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Замінено на <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_on_hold_settings_home_page (7690464049464805856) --> + <skip /> + <!-- no translation found for power_incompatible_charging_settings_home_page (1261756225093962684) --> + <skip /> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Залишилося приблизно <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"Залишилося приблизно <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"Згідно з даними про використання залишилося приблизно <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -483,9 +489,12 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Бездротове заряджання"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Заряджання"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"Не заряджається"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Підключено, не заряджається"</string> + <!-- no translation found for battery_info_status_not_charging (1103084691314264664) --> + <skip /> <string name="battery_info_status_full" msgid="1339002294876531312">"Заряджено"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Повністю заряджено"</string> + <!-- no translation found for battery_info_status_charging_on_hold (6364355145521694438) --> + <skip /> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Керується адміністратором"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Керується налаштуваннями з обмеженнями"</string> <string name="disabled" msgid="8017887509554714950">"Вимкнено"</string> diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml index 0dcb12fb0e64..020680e69e21 100644 --- a/packages/SettingsLib/res/values-ur/strings.xml +++ b/packages/SettingsLib/res/values-ur/strings.xml @@ -154,6 +154,7 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"امیجنگ"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"ہیڈ فون"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"ان پٹ پیریفرل"</string> + <string name="bluetooth_talkback_hearing_aids" msgid="3983279945542595479">"سماعتی آلات"</string> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"بلوٹوتھ"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wifi آف ہے۔"</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wifi غیر منسلک ہو گیا۔"</string> @@ -455,6 +456,8 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"درج ذیل کے لیے رنگ کی اصلاح مددگار ثابت ہو سکتی ہے:<br/> <ol> <li>&nbsp;جب آپ رنگوں کو مزید درست طریقے سے دیکھنا چاہیں</li> <li>&nbsp;فوکس کرنے میں مدد کرنے کے لئے رنگوں کو ہٹانا چاہیں</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> کے ذریعہ منسوخ کردیا گیا"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <string name="power_charging_on_hold_settings_home_page" msgid="7690464049464805856">"<xliff:g id="LEVEL">%1$s</xliff:g> - بیٹری کی حفاظت کرنے کے لیے چارجنگ ہولڈ پر ہے"</string> + <string name="power_incompatible_charging_settings_home_page" msgid="1261756225093962684">"<xliff:g id="LEVEL">%1$s</xliff:g> - چارجنگ ایکسیسری کی جانچ کی جا رہی ہے"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"تقریباً <xliff:g id="TIME_REMAINING">%1$s</xliff:g> باقی ہے"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"تقریباً <xliff:g id="TIME_REMAINING">%1$s</xliff:g> باقی ہے (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"آپ کے استعمال کی بنیاد پر تقریباً <xliff:g id="TIME_REMAINING">%1$s</xliff:g> باقی ہے"</string> @@ -483,9 +486,10 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"وائرلیس طریقے سے چارج ہو رہی ہے"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"چارج ہو رہی ہے"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"چارج نہیں ہو رہا ہے"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"منسلک ہے، چارج نہیں ہو رہی ہے"</string> + <string name="battery_info_status_not_charging" msgid="1103084691314264664">"منسلک ہے، لیکن چارج نہیں ہو رہا ہے"</string> <string name="battery_info_status_full" msgid="1339002294876531312">"چارج ہو گئی"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"مکمل طور پر چارج ہو گئی"</string> + <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"چارجنگ ہولڈ پر ہے"</string> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"کنٹرول کردہ بذریعہ منتظم"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"محدود کردہ ترتیب کے زیر انتظام ہے"</string> <string name="disabled" msgid="8017887509554714950">"غیر فعال"</string> diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml index c94ff4d1a8f0..3acb9cd422ac 100644 --- a/packages/SettingsLib/res/values-uz/strings.xml +++ b/packages/SettingsLib/res/values-uz/strings.xml @@ -154,6 +154,8 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Kamera"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Quloqchin"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Kiritish qurilmasi"</string> + <!-- no translation found for bluetooth_talkback_hearing_aids (3983279945542595479) --> + <skip /> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wi-Fi o‘chiq."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wi-Fi o‘chiq."</string> @@ -455,6 +457,10 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Ranglarni tuzatishning foydasi:<br/> <ol> <li>&nbsp;Ranglar yanada aniqroq koʻrinadi</li> <li>&nbsp;Diqqatni qaratish uchun ortiqcha ranglarni olib tashlash imkonini beradi</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> bilan almashtirildi"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_on_hold_settings_home_page (7690464049464805856) --> + <skip /> + <!-- no translation found for power_incompatible_charging_settings_home_page (1261756225093962684) --> + <skip /> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Taxminan <xliff:g id="TIME_REMAINING">%1$s</xliff:g> qoldi"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"Taxminan <xliff:g id="TIME_REMAINING">%1$s</xliff:g> qoldi (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"Quvvati tugashiga taxminan <xliff:g id="TIME_REMAINING">%1$s</xliff:g> qoldi"</string> @@ -483,9 +489,12 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Simsiz quvvat olmoqda"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Quvvat olmoqda"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"Quvvat olmayapti"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Ulangan, quvvat olmayapti"</string> + <!-- no translation found for battery_info_status_not_charging (1103084691314264664) --> + <skip /> <string name="battery_info_status_full" msgid="1339002294876531312">"Quvvat oldi"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Toʻliq quvvatlandi"</string> + <!-- no translation found for battery_info_status_charging_on_hold (6364355145521694438) --> + <skip /> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Administrator tomonidan boshqariladi"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Cheklangan sozlama tomonidan boshqariladi"</string> <string name="disabled" msgid="8017887509554714950">"Oʻchiq"</string> diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml index 03f0770bad8d..fcc049ddcdae 100644 --- a/packages/SettingsLib/res/values-vi/strings.xml +++ b/packages/SettingsLib/res/values-vi/strings.xml @@ -154,6 +154,8 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Tạo ảnh"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Tai nghe"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Thiết bị ngoại vi vào"</string> + <!-- no translation found for bluetooth_talkback_hearing_aids (3983279945542595479) --> + <skip /> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Đã tắt Wi-Fi."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Đã ngắt kết nối Wi-Fi."</string> @@ -455,6 +457,10 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Tính năng chỉnh màu có thể giúp ích khi bạn muốn:<br/> <ol> <li>&nbsp;Thấy màu sắc chính xác hơn</li> <li>&nbsp;Loại bỏ bớt màu để tập trung</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Bị ghi đè bởi <xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_on_hold_settings_home_page (7690464049464805856) --> + <skip /> + <!-- no translation found for power_incompatible_charging_settings_home_page (1261756225093962684) --> + <skip /> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Còn khoảng <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"Còn khoảng <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"Còn khoảng <xliff:g id="TIME_REMAINING">%1$s</xliff:g> dựa trên mức sử dụng của bạn"</string> @@ -483,9 +489,12 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Đang sạc không dây"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Đang sạc"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"Hiện không sạc"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Đã kết nối nhưng chưa sạc"</string> + <!-- no translation found for battery_info_status_not_charging (1103084691314264664) --> + <skip /> <string name="battery_info_status_full" msgid="1339002294876531312">"Đã sạc"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Đã sạc đầy"</string> + <!-- no translation found for battery_info_status_charging_on_hold (6364355145521694438) --> + <skip /> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Do quản trị viên kiểm soát"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Do chế độ Cài đặt hạn chế kiểm soát"</string> <string name="disabled" msgid="8017887509554714950">"Đã tắt"</string> diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml index 30db0331f99f..babcc07beaf2 100644 --- a/packages/SettingsLib/res/values-zh-rCN/strings.xml +++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml @@ -154,6 +154,7 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"成像设备"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"耳机"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"外围输入设备"</string> + <string name="bluetooth_talkback_hearing_aids" msgid="3983279945542595479">"助听器"</string> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"蓝牙"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"WLAN 已关闭。"</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"WLAN 连接已断开。"</string> @@ -455,6 +456,8 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"“色彩校正”功能适用于以下情况:<br/> <ol> <li>您想更准确地查看颜色</li> <li>您想移除颜色以提高专注程度</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"已被“<xliff:g id="TITLE">%1$s</xliff:g>”覆盖"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <string name="power_charging_on_hold_settings_home_page" msgid="7690464049464805856">"<xliff:g id="LEVEL">%1$s</xliff:g> - 为保护电池,充电已暂停"</string> + <string name="power_incompatible_charging_settings_home_page" msgid="1261756225093962684">"<xliff:g id="LEVEL">%1$s</xliff:g> - 正在检查充电配件"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"大约还可使用<xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"大约还可使用<xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"根据您的使用情况,大约还可使用<xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -483,9 +486,10 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"正在无线充电"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"正在充电"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"未在充电"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"已连接,未充电"</string> + <string name="battery_info_status_not_charging" msgid="1103084691314264664">"已连接,但未充电"</string> <string name="battery_info_status_full" msgid="1339002294876531312">"已充满电"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"已充满电"</string> + <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"目前暂停充电"</string> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"由管理员控制"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"由受限设置控制"</string> <string name="disabled" msgid="8017887509554714950">"已停用"</string> diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml index 2ce4de9ee7e0..390ae37d7e85 100644 --- a/packages/SettingsLib/res/values-zh-rHK/strings.xml +++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml @@ -154,6 +154,8 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"映像設備"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"耳機"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"輸入周邊設備"</string> + <!-- no translation found for bluetooth_talkback_hearing_aids (3983279945542595479) --> + <skip /> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"藍牙"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"Wi-Fi 已關閉。"</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wi-Fi 連線已中斷。"</string> @@ -455,6 +457,10 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"「色彩校正」功能適用於以下情況::<br/> <ol> <li>&nbsp;你想讓裝置顯示更準確的色彩</li> <li>&nbsp;你想移除色彩以提高專注力</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"已由「<xliff:g id="TITLE">%1$s</xliff:g>」覆寫"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_on_hold_settings_home_page (7690464049464805856) --> + <skip /> + <!-- no translation found for power_incompatible_charging_settings_home_page (1261756225093962684) --> + <skip /> <string name="power_remaining_duration_only" msgid="8264199158671531431">"還有大約 <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"還有大約 <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"根據你的使用情況,還有大約 <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -483,9 +489,12 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"無線充電中"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"正在充電"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"非充電中"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"已連接,非充電中"</string> + <!-- no translation found for battery_info_status_not_charging (1103084691314264664) --> + <skip /> <string name="battery_info_status_full" msgid="1339002294876531312">"已充滿電"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"充電完成"</string> + <!-- no translation found for battery_info_status_charging_on_hold (6364355145521694438) --> + <skip /> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"已由管理員停用"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"由「受限設定」控制"</string> <string name="disabled" msgid="8017887509554714950">"已停用"</string> diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml index 2fac076a51cc..5f4b9ed77bf4 100644 --- a/packages/SettingsLib/res/values-zh-rTW/strings.xml +++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml @@ -154,6 +154,8 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"顯像裝置"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"頭戴式耳機"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"周邊輸入裝置"</string> + <!-- no translation found for bluetooth_talkback_hearing_aids (3983279945542595479) --> + <skip /> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"藍牙"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"已關閉 Wi-Fi。"</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"Wi-Fi 連線已中斷。"</string> @@ -369,7 +371,7 @@ <string name="show_hw_screen_updates_summary" msgid="3539770072741435691">"繪圖時在視窗中閃爍顯示畫面"</string> <string name="show_hw_layers_updates" msgid="5268370750002509767">"顯示硬體層更新"</string> <string name="show_hw_layers_updates_summary" msgid="5850955890493054618">"在硬體層更新時閃綠燈"</string> - <string name="debug_hw_overdraw" msgid="8944851091008756796">"針對 GPU 重複繪圖進行偵錯"</string> + <string name="debug_hw_overdraw" msgid="8944851091008756796">"針對 GPU 過度繪製進行偵錯"</string> <string name="disable_overlays" msgid="4206590799671557143">"停用硬體重疊圖層"</string> <string name="disable_overlays_summary" msgid="1954852414363338166">"一律使用 GPU 進行畫面合成"</string> <string name="simulate_color_space" msgid="1206503300335835151">"模擬色彩空間"</string> @@ -455,6 +457,10 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"「色彩校正」功能適用於以下情況:<br/> <ol> <li>&nbsp;你想讓裝置顯示更準確的色彩</li> <li>&nbsp;你想移除色彩以提升專注力</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"已改為<xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <!-- no translation found for power_charging_on_hold_settings_home_page (7690464049464805856) --> + <skip /> + <!-- no translation found for power_incompatible_charging_settings_home_page (1261756225093962684) --> + <skip /> <string name="power_remaining_duration_only" msgid="8264199158671531431">"還能使用約 <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"目前電量為 <xliff:g id="LEVEL">%2$s</xliff:g>,還能使用約 <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"根據你的使用情形,還能使用約 <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> @@ -483,9 +489,12 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"正在進行無線充電"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"充電中"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"非充電中"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"已連接,尚未充電"</string> + <!-- no translation found for battery_info_status_not_charging (1103084691314264664) --> + <skip /> <string name="battery_info_status_full" msgid="1339002294876531312">"充電完成"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"充電完成"</string> + <!-- no translation found for battery_info_status_charging_on_hold (6364355145521694438) --> + <skip /> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"已由管理員停用"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"由限制設定控管"</string> <string name="disabled" msgid="8017887509554714950">"已停用"</string> @@ -507,7 +516,7 @@ <string name="screen_zoom_summary_extremely_large" msgid="1438045624562358554">"最大"</string> <string name="screen_zoom_summary_custom" msgid="3468154096832912210">"自訂 (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string> <string name="content_description_menu_button" msgid="6254844309171779931">"選單"</string> - <string name="retail_demo_reset_message" msgid="5392824901108195463">"如要在示範模式中恢復原廠設定,請輸入密碼"</string> + <string name="retail_demo_reset_message" msgid="5392824901108195463">"如要在展示模式中恢復原廠設定,請輸入密碼"</string> <string name="retail_demo_reset_next" msgid="3688129033843885362">"下一步"</string> <string name="retail_demo_reset_title" msgid="1866911701095959800">"請輸入密碼"</string> <string name="active_input_method_subtypes" msgid="4232680535471633046">"啟用的輸入法"</string> diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml index 9a818082a624..af859526f94e 100644 --- a/packages/SettingsLib/res/values-zu/strings.xml +++ b/packages/SettingsLib/res/values-zu/strings.xml @@ -154,6 +154,7 @@ <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Ukwenza isithombe"</string> <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Amahedfoni"</string> <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Okokufaka okulawulwa yikhompuyutha"</string> + <string name="bluetooth_talkback_hearing_aids" msgid="3983279945542595479">"Imishini Yezindlebe"</string> <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"I-Bluetooth"</string> <string name="accessibility_wifi_off" msgid="1195445715254137155">"I-Wifi ivaliwe."</string> <string name="accessibility_no_wifi" msgid="5297119459491085771">"I-Wifi inqanyuliwe."</string> @@ -455,6 +456,8 @@ <string name="accessibility_display_daltonizer_preference_subtitle" msgid="1522101114585266455">"Ukulungiswa kombala kungasiza uma ufuna ukwenza lokhu:<br/><br/> <ol> <li>&nbsp;Ukubona imibala ngokunembe kakhulu</li> <li>&nbsp;Ukususa imibala ukukusiza ukuthi ugxile</li> </ol>"</string> <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Igitshezwe ngaphezulu yi-<xliff:g id="TITLE">%1$s</xliff:g>"</string> <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> + <string name="power_charging_on_hold_settings_home_page" msgid="7690464049464805856">"<xliff:g id="LEVEL">%1$s</xliff:g> - Ukushaja kumisiwe ukuze kuvikelwe ibhethri"</string> + <string name="power_incompatible_charging_settings_home_page" msgid="1261756225093962684">"<xliff:g id="LEVEL">%1$s</xliff:g> - Kuhlolwa okokushaja"</string> <string name="power_remaining_duration_only" msgid="8264199158671531431">"Cishe u-<xliff:g id="TIME_REMAINING">%1$s</xliff:g> osele"</string> <string name="power_discharging_duration" msgid="1076561255466053220">"Cishe u-<xliff:g id="TIME_REMAINING">%1$s</xliff:g> osele (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_remaining_duration_only_enhanced" msgid="2527842780666073218">"Cishe u-<xliff:g id="TIME_REMAINING">%1$s</xliff:g> osele ngokususelwe ekusebenziseni wakho"</string> @@ -483,9 +486,10 @@ <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Iyashaja ngaphandle kwentambo"</string> <string name="battery_info_status_charging_dock" msgid="8573274094093364791">"Iyashaja"</string> <string name="battery_info_status_discharging" msgid="6962689305413556485">"Ayishaji"</string> - <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Ixhunyiwe, ayishaji"</string> + <string name="battery_info_status_not_charging" msgid="1103084691314264664">"Ixhunyiwe, kodwa ayishaji"</string> <string name="battery_info_status_full" msgid="1339002294876531312">"Kushajiwe"</string> <string name="battery_info_status_full_charged" msgid="3536054261505567948">"Ishaje Ngokuphelele"</string> + <string name="battery_info_status_charging_on_hold" msgid="6364355145521694438">"Ukushaja kumisiwe"</string> <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Kulawulwa umqondisi"</string> <string name="disabled_by_app_ops_text" msgid="8373595926549098012">"Kulawulwe Isethingi Elikhawulelwe"</string> <string name="disabled" msgid="8017887509554714950">"Akusebenzi"</string> diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/InterestingConfigChanges.java b/packages/SettingsLib/src/com/android/settingslib/applications/InterestingConfigChanges.java index 5d520ce5d81f..7e2d0af5c075 100644 --- a/packages/SettingsLib/src/com/android/settingslib/applications/InterestingConfigChanges.java +++ b/packages/SettingsLib/src/com/android/settingslib/applications/InterestingConfigChanges.java @@ -21,6 +21,8 @@ import android.content.pm.ActivityInfo; import android.content.res.Configuration; import android.content.res.Resources; +import androidx.annotation.NonNull; + /** * A class for applying config changes and determing if doing so resulting in any "interesting" * changes. @@ -48,8 +50,15 @@ public class InterestingConfigChanges { */ @SuppressLint("NewApi") public boolean applyNewConfig(Resources res) { + return applyNewConfig(res.getConfiguration()); + } + + /** + * Applies the given config change and returns whether an "interesting" change happened. + */ + public boolean applyNewConfig(@NonNull Configuration configuration) { int configChanges = mLastConfiguration.updateFrom( - Configuration.generateDelta(mLastConfiguration, res.getConfiguration())); + Configuration.generateDelta(mLastConfiguration, configuration)); return (configChanges & (mFlags)) != 0; } } diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LeAudioProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LeAudioProfile.java index 57012aabb123..931a6f149b84 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LeAudioProfile.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LeAudioProfile.java @@ -3,17 +3,17 @@ */ /* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.bluetooth; @@ -23,6 +23,7 @@ import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothClass; +import android.bluetooth.BluetoothCsipSetCoordinator; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothLeAudio; import android.bluetooth.BluetoothProfile; @@ -30,6 +31,7 @@ import android.content.Context; import android.os.Build; import android.util.Log; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; @@ -57,13 +59,12 @@ public class LeAudioProfile implements LocalBluetoothProfile { private static final int ORDINAL = 1; // These callbacks run on the main thread. - private final class LeAudioServiceListener - implements BluetoothProfile.ServiceListener { + private final class LeAudioServiceListener implements BluetoothProfile.ServiceListener { @RequiresApi(Build.VERSION_CODES.S) public void onServiceConnected(int profile, BluetoothProfile proxy) { if (DEBUG) { - Log.d(TAG,"Bluetooth service connected"); + Log.d(TAG, "Bluetooth service connected"); } mService = (BluetoothLeAudio) proxy; // We just bound to the service, so refresh the UI for any connected LeAudio devices. @@ -78,8 +79,7 @@ public class LeAudioProfile implements LocalBluetoothProfile { } device = mDeviceManager.addDevice(nextDevice); } - device.onProfileStateChanged(LeAudioProfile.this, - BluetoothProfile.STATE_CONNECTED); + device.onProfileStateChanged(LeAudioProfile.this, BluetoothProfile.STATE_CONNECTED); device.refresh(); } @@ -89,7 +89,7 @@ public class LeAudioProfile implements LocalBluetoothProfile { public void onServiceDisconnected(int profile) { if (DEBUG) { - Log.d(TAG,"Bluetooth service disconnected"); + Log.d(TAG, "Bluetooth service disconnected"); } mProfileManager.callServiceDisconnectedListeners(); mIsProfileReady = false; @@ -105,7 +105,9 @@ public class LeAudioProfile implements LocalBluetoothProfile { return BluetoothProfile.LE_AUDIO; } - LeAudioProfile(Context context, CachedBluetoothDeviceManager deviceManager, + LeAudioProfile( + Context context, + CachedBluetoothDeviceManager deviceManager, LocalBluetoothProfileManager profileManager) { mContext = context; mDeviceManager = deviceManager; @@ -113,8 +115,7 @@ public class LeAudioProfile implements LocalBluetoothProfile { mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); mBluetoothAdapter.getProfileProxy( - context, new LeAudioServiceListener(), - BluetoothProfile.LE_AUDIO); + context, new LeAudioServiceListener(), BluetoothProfile.LE_AUDIO); } public boolean accessProfileEnabled() { @@ -126,18 +127,22 @@ public class LeAudioProfile implements LocalBluetoothProfile { } public List<BluetoothDevice> getConnectedDevices() { - return getDevicesByStates(new int[] { - BluetoothProfile.STATE_CONNECTED, - BluetoothProfile.STATE_CONNECTING, - BluetoothProfile.STATE_DISCONNECTING}); + return getDevicesByStates( + new int[] { + BluetoothProfile.STATE_CONNECTED, + BluetoothProfile.STATE_CONNECTING, + BluetoothProfile.STATE_DISCONNECTING + }); } public List<BluetoothDevice> getConnectableDevices() { - return getDevicesByStates(new int[] { - BluetoothProfile.STATE_DISCONNECTED, - BluetoothProfile.STATE_CONNECTED, - BluetoothProfile.STATE_CONNECTING, - BluetoothProfile.STATE_DISCONNECTING}); + return getDevicesByStates( + new int[] { + BluetoothProfile.STATE_DISCONNECTED, + BluetoothProfile.STATE_CONNECTED, + BluetoothProfile.STATE_CONNECTING, + BluetoothProfile.STATE_DISCONNECTING + }); } private List<BluetoothDevice> getDevicesByStates(int[] states) { @@ -148,8 +153,8 @@ public class LeAudioProfile implements LocalBluetoothProfile { } /* - * @hide - */ + * @hide + */ public boolean connect(BluetoothDevice device) { if (mService == null) { return false; @@ -158,8 +163,8 @@ public class LeAudioProfile implements LocalBluetoothProfile { } /* - * @hide - */ + * @hide + */ public boolean disconnect(BluetoothDevice device) { if (mService == null) { return false; @@ -174,6 +179,14 @@ public class LeAudioProfile implements LocalBluetoothProfile { return mService.getConnectionState(device); } + /** Get group id for {@link BluetoothDevice}. */ + public int getGroupId(@NonNull BluetoothDevice device) { + if (mService == null) { + return BluetoothCsipSetCoordinator.GROUP_ID_INVALID; + } + return mService.getGroupId(device); + } + public boolean setActiveDevice(BluetoothDevice device) { if (mBluetoothAdapter == null) { return false; @@ -193,29 +206,28 @@ public class LeAudioProfile implements LocalBluetoothProfile { /** * Get Lead device for the group. * - * Lead device is the device that can be used as an active device in the system. - * Active devices points to the Audio Device for the Le Audio group. - * This method returns the Lead devices for the connected LE Audio - * group and this device should be used in the setActiveDevice() method by other parts - * of the system, which wants to set to active a particular Le Audio group. + * <p>Lead device is the device that can be used as an active device in the system. Active + * devices points to the Audio Device for the Le Audio group. This method returns the Lead + * devices for the connected LE Audio group and this device should be used in the + * setActiveDevice() method by other parts of the system, which wants to set to active a + * particular Le Audio group. * - * Note: getActiveDevice() returns the Lead device for the currently active LE Audio group. + * <p>Note: getActiveDevice() returns the Lead device for the currently active LE Audio group. * Note: When Lead device gets disconnected while Le Audio group is active and has more devices - * in the group, then Lead device will not change. If Lead device gets disconnected, for the - * Le Audio group which is not active, a new Lead device will be chosen + * in the group, then Lead device will not change. If Lead device gets disconnected, for the Le + * Audio group which is not active, a new Lead device will be chosen * * @param groupId The group id. * @return group lead device. - * * @hide */ @RequiresApi(Build.VERSION_CODES.TIRAMISU) public @Nullable BluetoothDevice getConnectedGroupLeadDevice(int groupId) { if (DEBUG) { - Log.d(TAG,"getConnectedGroupLeadDevice"); + Log.d(TAG, "getConnectedGroupLeadDevice"); } if (mService == null) { - Log.e(TAG,"No service."); + Log.e(TAG, "No service."); return null; } return mService.getConnectedGroupLeadDevice(groupId); @@ -310,10 +322,10 @@ public class LeAudioProfile implements LocalBluetoothProfile { } if (mService != null) { try { - BluetoothAdapter.getDefaultAdapter().closeProfileProxy(BluetoothProfile.LE_AUDIO, - mService); + BluetoothAdapter.getDefaultAdapter() + .closeProfileProxy(BluetoothProfile.LE_AUDIO, mService); mService = null; - }catch (Throwable t) { + } catch (Throwable t) { Log.w(TAG, "Error cleaning up LeAudio proxy", t); } } diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcast.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcast.java index de21c541c7e4..934870507a20 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcast.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcast.java @@ -84,6 +84,8 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile { Settings.Secure.getUriFor(Settings.Secure.BLUETOOTH_LE_BROADCAST_PROGRAM_INFO), Settings.Secure.getUriFor(Settings.Secure.BLUETOOTH_LE_BROADCAST_CODE), Settings.Secure.getUriFor(Settings.Secure.BLUETOOTH_LE_BROADCAST_APP_SOURCE_NAME), + Settings.Secure.getUriFor( + Settings.Secure.BLUETOOTH_LE_BROADCAST_IMPROVE_COMPATIBILITY), }; private BluetoothLeBroadcast mServiceBroadcast; @@ -96,6 +98,7 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile { private String mNewAppSourceName = ""; private boolean mIsBroadcastProfileReady = false; private boolean mIsBroadcastAssistantProfileReady = false; + private boolean mImproveCompatibility = false; private String mProgramInfo; private byte[] mBroadcastCode; private Executor mExecutor; @@ -391,6 +394,52 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile { * <p>If the system started the LE Broadcast, then the system calls the corresponding callback * {@link BluetoothLeBroadcast.Callback}. */ + public void startPrivateBroadcast() { + mNewAppSourceName = "Sharing audio"; + if (mServiceBroadcast == null) { + Log.d(TAG, "The BluetoothLeBroadcast is null when starting the private broadcast."); + return; + } + if (mServiceBroadcast.getAllBroadcastMetadata().size() + >= mServiceBroadcast.getMaximumNumberOfBroadcasts()) { + Log.d(TAG, "Skip starting the broadcast due to number limit."); + return; + } + String programInfo = getProgramInfo(); + boolean improveCompatibility = getImproveCompatibility(); + if (DEBUG) { + Log.d( + TAG, + "startBroadcast: language = null , programInfo = " + + programInfo + + ", improveCompatibility = " + + improveCompatibility); + } + // Current broadcast framework only support one subgroup + BluetoothLeBroadcastSubgroupSettings subgroupSettings = + buildBroadcastSubgroupSettings( + /* language= */ null, programInfo, improveCompatibility); + BluetoothLeBroadcastSettings settings = + buildBroadcastSettings( + true, // TODO: set to false after framework fix + TextUtils.isEmpty(programInfo) ? null : programInfo, + (mBroadcastCode != null && mBroadcastCode.length > 0) + ? mBroadcastCode + : null, + ImmutableList.of(subgroupSettings)); + mServiceBroadcast.startBroadcast(settings); + } + + /** + * Start the private Broadcast for personal audio sharing or qr code sharing. + * + * <p>The broadcast will use random string for both broadcast name and subgroup program info; + * The broadcast will use random string for broadcast code; The broadcast will only have one + * subgroup due to system limitation; The subgroup language will be null. + * + * <p>If the system started the LE Broadcast, then the system calls the corresponding callback + * {@link BluetoothLeBroadcast.Callback}. + */ public void startPrivateBroadcast(int quality) { mNewAppSourceName = "Sharing audio"; if (mServiceBroadcast == null) { @@ -408,7 +457,11 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile { } // Current broadcast framework only support one subgroup BluetoothLeBroadcastSubgroupSettings subgroupSettings = - buildBroadcastSubgroupSettings(/* language= */ null, programInfo, quality); + buildBroadcastSubgroupSettings( + /* language= */ null, + programInfo, + /* improveCompatibility= */ + BluetoothLeBroadcastSubgroupSettings.QUALITY_STANDARD == quality); BluetoothLeBroadcastSettings settings = buildBroadcastSettings( true, // TODO: set to false after framework fix @@ -437,7 +490,7 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile { } private BluetoothLeBroadcastSubgroupSettings buildBroadcastSubgroupSettings( - @Nullable String language, @Nullable String programInfo, int quality) { + @Nullable String language, @Nullable String programInfo, boolean improveCompatibility) { BluetoothLeAudioContentMetadata metadata = new BluetoothLeAudioContentMetadata.Builder() .setLanguage(language) @@ -447,7 +500,10 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile { // metadata to keep legacy UI working. mBluetoothLeAudioContentMetadata = metadata; return new BluetoothLeBroadcastSubgroupSettings.Builder() - .setPreferredQuality(quality) + .setPreferredQuality( + improveCompatibility + ? BluetoothLeBroadcastSubgroupSettings.QUALITY_STANDARD + : BluetoothLeBroadcastSubgroupSettings.QUALITY_HIGH) .setContentMetadata(mBluetoothLeAudioContentMetadata) .build(); } @@ -513,6 +569,36 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile { } } + /** Get compatibility config for broadcast. */ + public boolean getImproveCompatibility() { + return mImproveCompatibility; + } + + /** Set compatibility config for broadcast. */ + public void setImproveCompatibility(boolean improveCompatibility) { + setImproveCompatibility(improveCompatibility, /* updateContentResolver= */ true); + } + + private void setImproveCompatibility( + boolean improveCompatibility, boolean updateContentResolver) { + if (mImproveCompatibility == improveCompatibility) { + Log.d(TAG, "setImproveCompatibility: improveCompatibility is not changed"); + return; + } + mImproveCompatibility = improveCompatibility; + if (updateContentResolver) { + if (mContentResolver == null) { + Log.d(TAG, "mContentResolver is null"); + return; + } + Log.d(TAG, "Set improveCompatibility to: " + improveCompatibility); + Settings.Secure.putString( + mContentResolver, + Settings.Secure.BLUETOOTH_LE_BROADCAST_IMPROVE_COMPATIBILITY, + improveCompatibility ? "1" : "0"); + } + } + private void setLatestBroadcastId(int broadcastId) { Log.d(TAG, "setLatestBroadcastId: mBroadcastId is " + broadcastId); mBroadcastId = broadcastId; @@ -600,6 +686,14 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile { Settings.Secure.getString( mContentResolver, Settings.Secure.BLUETOOTH_LE_BROADCAST_APP_SOURCE_NAME); setAppSourceName(appSourceName, /* updateContentResolver= */ false); + + String improveCompatibility = + Settings.Secure.getString( + mContentResolver, + Settings.Secure.BLUETOOTH_LE_BROADCAST_IMPROVE_COMPATIBILITY); + setImproveCompatibility( + improveCompatibility == null ? false : improveCompatibility.equals("1"), + /* updateContentResolver= */ false); } private void updateBroadcastInfoFromBroadcastMetadata( diff --git a/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java index d6f1eab442fa..15f33d2cff42 100644 --- a/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java +++ b/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java @@ -229,6 +229,17 @@ public class PhoneMediaDevice extends MediaDevice { @SuppressWarnings("NewApi") @Override public String getId() { + if (com.android.media.flags.Flags.enableAudioPoliciesDeviceAndBluetoothController()) { + // Note: be careful when removing this flag. Instead of just removing it, you might want + // to replace it with SDK_INT >= 35. Explanation: The presence of SDK checks in settings + // lib suggests that a mainline component may depend on this code. Which means removing + // this "if" (and using always the route info id) could mean a regression on mainline + // code running on a device that's running API 34 or older. Unfortunately, we cannot + // check the API level at the moment of writing this code because the API level has not + // been bumped, yet. + return mRouteInfo.getId(); + } + String id; switch (mRouteInfo.getType()) { case TYPE_WIRED_HEADSET: diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/PhoneMediaDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/PhoneMediaDeviceTest.java index 1746befbfa4d..ceba9be70487 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/PhoneMediaDeviceTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/PhoneMediaDeviceTest.java @@ -31,10 +31,15 @@ import static org.mockito.Mockito.when; import android.content.Context; import android.media.MediaRoute2Info; +import android.platform.test.annotations.DisableFlags; +import android.platform.test.annotations.EnableFlags; +import android.platform.test.flag.junit.SetFlagsRule; +import com.android.media.flags.Flags; import com.android.settingslib.R; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; @@ -45,6 +50,8 @@ import org.robolectric.RuntimeEnvironment; @RunWith(RobolectricTestRunner.class) public class PhoneMediaDeviceTest { + @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); + @Mock private MediaRoute2Info mInfo; @@ -110,8 +117,18 @@ public class PhoneMediaDeviceTest { .isEqualTo(mContext.getString(R.string.media_transfer_this_device_name)); } + @EnableFlags(Flags.FLAG_ENABLE_AUDIO_POLICIES_DEVICE_AND_BLUETOOTH_CONTROLLER) + @Test + public void getId_whenAdvancedWiredRoutingEnabled_returnCorrectId() { + String fakeId = "foo"; + when(mInfo.getId()).thenReturn(fakeId); + + assertThat(mPhoneMediaDevice.getId()).isEqualTo(fakeId); + } + + @DisableFlags(Flags.FLAG_ENABLE_AUDIO_POLICIES_DEVICE_AND_BLUETOOTH_CONTROLLER) @Test - public void getId_returnCorrectId() { + public void getId_whenAdvancedWiredRoutingDisabled_returnCorrectId() { when(mInfo.getType()).thenReturn(TYPE_WIRED_HEADPHONES); assertThat(mPhoneMediaDevice.getId()) diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java index 2d442f4c0e6e..3a46f4e96ccb 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java @@ -406,7 +406,7 @@ public class SettingsProvider extends ContentProvider { Process.THREAD_PRIORITY_BACKGROUND); mHandlerThread.start(); mHandler = new Handler(mHandlerThread.getLooper()); - mSettingsRegistry = new SettingsRegistry(); + mSettingsRegistry = new SettingsRegistry(mHandlerThread.getLooper()); } SettingsState.cacheSystemPackageNamesAndSystemSignature(getContext()); synchronized (mLock) { @@ -2896,8 +2896,8 @@ public class SettingsProvider extends ContentProvider { private String mSettingsCreationBuildId; - public SettingsRegistry() { - mHandler = new MyHandler(getContext().getMainLooper()); + SettingsRegistry(Looper looper) { + mHandler = new MyHandler(looper); mGenerationRegistry = new GenerationRegistry(UserManager.getMaxSupportedUsers()); mBackupManager = new BackupManager(getContext()); } diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index cc63996494a0..d38454221f76 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -343,6 +343,7 @@ <uses-permission android:name="android.permission.REQUEST_COMPANION_PROFILE_GLASSES" /> <uses-permission android:name="android.permission.REQUEST_COMPANION_SELF_MANAGED" /> <uses-permission android:name="android.permission.USE_COMPANION_TRANSPORTS" /> + <uses-permission android:name="android.permission.REQUEST_OBSERVE_DEVICE_UUID_PRESENCE" /> <uses-permission android:name="android.permission.MANAGE_APPOPS" /> <uses-permission android:name="android.permission.WATCH_APPOPS" /> diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp index d61ae7eccc42..80656e9253db 100644 --- a/packages/SystemUI/Android.bp +++ b/packages/SystemUI/Android.bp @@ -361,6 +361,7 @@ android_library { "androidx.test.ext.junit", "androidx.test.ext.truth", "kotlin-test", + "SystemUICustomizationTestUtils", ], libs: [ "android.test.runner", @@ -439,6 +440,7 @@ android_robolectric_test { "androidx.test.ext.junit", "inline-mockito-robolectric-prebuilt", "platform-parametric-runner-lib", + "SystemUICustomizationTestUtils", ], libs: [ "android.test.runner", diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig index 323613077a70..2c35c777ab12 100644 --- a/packages/SystemUI/aconfig/systemui.aconfig +++ b/packages/SystemUI/aconfig/systemui.aconfig @@ -89,6 +89,13 @@ flag { } flag { + name: "notification_avalanche_suppression" + namespace: "systemui" + description: "After notification avalanche floodgate event, suppress HUNs completely." + bug: "321089634" +} + +flag { name: "notification_background_tint_optimization" namespace: "systemui" description: "Re-enable the codepath that removed tinting of notifications when the" diff --git a/packages/SystemUI/compose/facade/disabled/src/com/android/systemui/compose/ComposeFacade.kt b/packages/SystemUI/compose/facade/disabled/src/com/android/systemui/compose/ComposeFacade.kt index 2052e2c01410..a7557d8880e3 100644 --- a/packages/SystemUI/compose/facade/disabled/src/com/android/systemui/compose/ComposeFacade.kt +++ b/packages/SystemUI/compose/facade/disabled/src/com/android/systemui/compose/ComposeFacade.kt @@ -17,6 +17,7 @@ package com.android.systemui.compose +import android.app.Dialog import android.content.Context import android.view.View import android.view.WindowInsets @@ -26,11 +27,13 @@ import com.android.systemui.bouncer.ui.BouncerDialogFactory import com.android.systemui.bouncer.ui.viewmodel.BouncerViewModel import com.android.systemui.communal.ui.viewmodel.BaseCommunalViewModel import com.android.systemui.communal.widgets.WidgetConfigurator +import com.android.systemui.keyboard.stickykeys.ui.viewmodel.StickyKeysIndicatorViewModel import com.android.systemui.people.ui.viewmodel.PeopleViewModel import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel import com.android.systemui.scene.shared.model.Scene import com.android.systemui.scene.shared.model.SceneKey import com.android.systemui.scene.ui.viewmodel.SceneContainerViewModel +import com.android.systemui.statusbar.phone.SystemUIDialogFactory import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.StateFlow @@ -78,6 +81,13 @@ object ComposeFacade : BaseComposeFacade { throwComposeUnavailableError() } + override fun createStickyKeysDialog( + dialogFactory: SystemUIDialogFactory, + viewModel: StickyKeysIndicatorViewModel + ): Dialog { + throwComposeUnavailableError() + } + override fun createCommunalView( context: Context, viewModel: BaseCommunalViewModel, diff --git a/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/compose/ComposeFacade.kt b/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/compose/ComposeFacade.kt index b607d596390d..d63939d3b699 100644 --- a/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/compose/ComposeFacade.kt +++ b/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/compose/ComposeFacade.kt @@ -16,6 +16,7 @@ package com.android.systemui.compose +import android.app.Dialog import android.content.Context import android.graphics.Point import android.view.View @@ -38,6 +39,8 @@ import com.android.systemui.communal.ui.compose.CommunalContainer import com.android.systemui.communal.ui.compose.CommunalHub import com.android.systemui.communal.ui.viewmodel.BaseCommunalViewModel import com.android.systemui.communal.widgets.WidgetConfigurator +import com.android.systemui.keyboard.stickykeys.ui.view.StickyKeysIndicator +import com.android.systemui.keyboard.stickykeys.ui.viewmodel.StickyKeysIndicatorViewModel import com.android.systemui.people.ui.compose.PeopleScreen import com.android.systemui.people.ui.viewmodel.PeopleViewModel import com.android.systemui.qs.footer.ui.compose.FooterActions @@ -47,6 +50,8 @@ import com.android.systemui.scene.shared.model.SceneKey import com.android.systemui.scene.ui.composable.ComposableScene import com.android.systemui.scene.ui.composable.SceneContainer import com.android.systemui.scene.ui.viewmodel.SceneContainerViewModel +import com.android.systemui.statusbar.phone.SystemUIDialogFactory +import com.android.systemui.statusbar.phone.create import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow @@ -120,6 +125,13 @@ object ComposeFacade : BaseComposeFacade { } } + override fun createStickyKeysDialog( + dialogFactory: SystemUIDialogFactory, + viewModel: StickyKeysIndicatorViewModel + ): Dialog { + return dialogFactory.create { StickyKeysIndicator(viewModel) } + } + override fun createCommunalView( context: Context, viewModel: BaseCommunalViewModel, diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt index 556a315894b8..409f15bb4bb8 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt @@ -624,17 +624,10 @@ private fun WidgetContent( modifier = modifier.align(Alignment.Center).allowGestures(allowed = !viewModel.isEditMode), factory = { context -> - // The AppWidgetHostView will inherit the interaction handler from the - // AppWidgetHost. So set the interaction handler here before creating the view, and - // then clear it after the view is created. This is a workaround due to the fact - // that the interaction handler cannot be specified when creating the view, - // and there are race conditions if it is set after the view is created. - model.appWidgetHost.setInteractionHandler(viewModel.getInteractionHandler()) val view = model.appWidgetHost .createViewForCommunal(context, model.appWidgetId, model.providerInfo) .apply { updateAppWidgetSize(Bundle.EMPTY, listOf(size)) } - model.appWidgetHost.setInteractionHandler(null) // Remove the extra padding applied to AppWidgetHostView to allow widgets to // occupy the entire box. The added padding is now adjusted to leave only sufficient // space for displaying the outline around the box when the widget is selected. diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyboard/stickykeys/ui/view/StickyKeysIndicator.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyboard/stickykeys/ui/view/StickyKeysIndicator.kt new file mode 100644 index 000000000000..68e57b5d51b8 --- /dev/null +++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyboard/stickykeys/ui/view/StickyKeysIndicator.kt @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.keyboard.stickykeys.ui.view + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.key +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import com.android.systemui.keyboard.stickykeys.shared.model.Locked +import com.android.systemui.keyboard.stickykeys.shared.model.ModifierKey +import com.android.systemui.keyboard.stickykeys.ui.viewmodel.StickyKeysIndicatorViewModel + +@Composable +fun StickyKeysIndicator(viewModel: StickyKeysIndicatorViewModel) { + val stickyKeys by viewModel.indicatorContent.collectAsState(emptyMap()) + StickyKeysIndicator(stickyKeys) +} + +@Composable +fun StickyKeysIndicator(stickyKeys: Map<ModifierKey, Locked>, modifier: Modifier = Modifier) { + Surface( + color = MaterialTheme.colorScheme.surface, + shape = MaterialTheme.shapes.medium, + modifier = modifier + ) { + Column( + horizontalAlignment = Alignment.CenterHorizontally, + modifier = Modifier.padding(16.dp) + ) { + stickyKeys.forEach { (key, isLocked) -> + key(key) { + Text( + text = key.text, + fontWeight = if (isLocked.locked) FontWeight.Bold else FontWeight.Normal + ) + } + } + } + } +} diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettings.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettings.kt index 9778e53d8f69..c027c499c0b7 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettings.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettings.kt @@ -16,17 +16,16 @@ package com.android.systemui.qs.ui.composable -import android.view.ContextThemeWrapper import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.defaultMinSize -import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.runtime.Composable -import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue -import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.unit.dp @@ -53,14 +52,6 @@ object QuickSettings { } } -@Composable -private fun QuickSettingsTheme(content: @Composable () -> Unit) { - val context = LocalContext.current - val themedContext = - remember(context) { ContextThemeWrapper(context, R.style.Theme_SystemUI_QuickSettings) } - CompositionLocalProvider(LocalContext provides themedContext) { content() } -} - private fun SceneScope.stateForQuickSettingsContent(): QSSceneAdapter.State { return when (val transitionState = layoutState.transitionState) { is TransitionState.Idle -> { @@ -115,6 +106,7 @@ private fun QuickSettingsContent( modifier: Modifier = Modifier, ) { val qsView by qsSceneAdapter.qsView.collectAsState(null) + val isCustomizing by qsSceneAdapter.isCustomizing.collectAsState() QuickSettingsTheme { val context = LocalContext.current @@ -124,14 +116,27 @@ private fun QuickSettingsContent( } } qsView?.let { view -> - AndroidView( - modifier = modifier.fillMaxSize().background(colorAttr(R.attr.underSurface)), - factory = { _ -> - qsSceneAdapter.setState(state) - view - }, - update = { qsSceneAdapter.setState(state) } - ) + Box( + modifier = + modifier + .fillMaxWidth() + .then( + if (isCustomizing) { + Modifier.fillMaxHeight() + } else { + Modifier.wrapContentHeight() + } + ) + ) { + AndroidView( + modifier = Modifier.fillMaxWidth().background(colorAttr(R.attr.underSurface)), + factory = { _ -> + qsSceneAdapter.setState(state) + view + }, + update = { qsSceneAdapter.setState(state) } + ) + } } } } diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt index d8c7290b76b8..bbfe0fda049a 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt @@ -24,31 +24,44 @@ import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut import androidx.compose.animation.shrinkVertically import androidx.compose.foundation.background +import androidx.compose.foundation.clipScrollableContainer +import androidx.compose.foundation.gestures.Orientation import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.wrapContentHeight +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll import androidx.compose.material3.MaterialTheme import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.platform.LocalLifecycleOwner import androidx.compose.ui.unit.dp import com.android.compose.animation.scene.SceneScope +import com.android.compose.animation.scene.TransitionState import com.android.compose.windowsizeclass.LocalWindowSizeClass import com.android.systemui.battery.BatteryMeterViewController +import com.android.systemui.compose.modifiers.sysuiResTag import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.notifications.ui.composable.HeadsUpNotificationSpace +import com.android.systemui.qs.footer.ui.compose.FooterActions import com.android.systemui.qs.ui.viewmodel.QuickSettingsSceneViewModel import com.android.systemui.scene.shared.model.SceneKey import com.android.systemui.scene.ui.composable.ComposableScene +import com.android.systemui.scene.ui.composable.toTransitionSceneKey import com.android.systemui.shade.ui.composable.CollapsedShadeHeader import com.android.systemui.shade.ui.composable.ExpandedShadeHeader import com.android.systemui.shade.ui.composable.Shade @@ -105,57 +118,120 @@ private fun SceneScope.QuickSettingsScene( ) { // TODO(b/280887232): implement the real UI. Box(modifier = modifier.fillMaxSize()) { - Box(modifier = Modifier.fillMaxSize()) { - val isCustomizing by viewModel.qsSceneAdapter.isCustomizing.collectAsState() - val collapsedHeaderHeight = - with(LocalDensity.current) { ShadeHeader.Dimensions.CollapsedHeight.roundToPx() } - Spacer( - modifier = - Modifier.element(Shade.Elements.ScrimBackground) - .fillMaxSize() - .background(MaterialTheme.colorScheme.scrim, shape = Shade.Shapes.Scrim) - ) - Column( - horizontalAlignment = Alignment.CenterHorizontally, - modifier = - Modifier.fillMaxSize().padding(start = 16.dp, end = 16.dp, bottom = 48.dp) - ) { - when (LocalWindowSizeClass.current.widthSizeClass) { - WindowWidthSizeClass.Compact -> - AnimatedVisibility( - visible = !isCustomizing, - enter = - expandVertically( - animationSpec = tween(1000), - initialHeight = { collapsedHeaderHeight }, - ) + fadeIn(tween(1000)), - exit = - shrinkVertically( - animationSpec = tween(1000), - targetHeight = { collapsedHeaderHeight }, - shrinkTowards = Alignment.Top, - ) + fadeOut(tween(1000)), - ) { - ExpandedShadeHeader( + val isCustomizing by viewModel.qsSceneAdapter.isCustomizing.collectAsState() + val collapsedHeaderHeight = + with(LocalDensity.current) { ShadeHeader.Dimensions.CollapsedHeight.roundToPx() } + val lifecycleOwner = LocalLifecycleOwner.current + val footerActionsViewModel = + remember(lifecycleOwner, viewModel) { + viewModel.getFooterActionsViewModel(lifecycleOwner) + } + val scrollState = rememberScrollState() + // When animating into the scene, we don't want it to be able to scroll, as it could mess + // up with the expansion animation. + val isScrollable = + when (val state = layoutState.transitionState) { + is TransitionState.Idle -> true + is TransitionState.Transition -> { + state.fromScene == SceneKey.QuickSettings.toTransitionSceneKey() + } + } + + LaunchedEffect(isCustomizing, scrollState) { + if (isCustomizing) { + scrollState.scrollTo(0) + } + } + + // This is the background for the whole scene, as the elements don't necessarily provide + // a background that extends to the edges. + Spacer( + modifier = + Modifier.element(Shade.Elements.ScrimBackground) + .fillMaxSize() + .background(MaterialTheme.colorScheme.scrim, shape = Shade.Shapes.Scrim) + ) + Column( + horizontalAlignment = Alignment.CenterHorizontally, + modifier = + Modifier.fillMaxSize() + // bottom should be tied to insets + .padding(bottom = 16.dp) + ) { + Box(modifier = Modifier.fillMaxSize().weight(1f)) { + val shadeHeaderAndQuickSettingsModifier = + if (isCustomizing) { + Modifier.fillMaxHeight().align(Alignment.TopCenter) + } else { + Modifier.verticalNestedScrollToScene() + .verticalScroll( + scrollState, + enabled = isScrollable, + ) + .clipScrollableContainer(Orientation.Horizontal) + .fillMaxWidth() + .wrapContentHeight(unbounded = true) + .align(Alignment.TopCenter) + } + + Column( + modifier = shadeHeaderAndQuickSettingsModifier, + ) { + when (LocalWindowSizeClass.current.widthSizeClass) { + WindowWidthSizeClass.Compact -> + AnimatedVisibility( + visible = !isCustomizing, + enter = + expandVertically( + animationSpec = tween(100), + initialHeight = { collapsedHeaderHeight }, + ) + fadeIn(tween(100)), + exit = + shrinkVertically( + animationSpec = tween(100), + targetHeight = { collapsedHeaderHeight }, + shrinkTowards = Alignment.Top, + ) + fadeOut(tween(100)), + ) { + ExpandedShadeHeader( + viewModel = viewModel.shadeHeaderViewModel, + createTintedIconManager = createTintedIconManager, + createBatteryMeterViewController = + createBatteryMeterViewController, + statusBarIconController = statusBarIconController, + modifier = Modifier.padding(horizontal = 16.dp), + ) + } + else -> + CollapsedShadeHeader( viewModel = viewModel.shadeHeaderViewModel, createTintedIconManager = createTintedIconManager, createBatteryMeterViewController = createBatteryMeterViewController, statusBarIconController = statusBarIconController, + modifier = Modifier.padding(horizontal = 16.dp), ) - } - else -> - CollapsedShadeHeader( - viewModel = viewModel.shadeHeaderViewModel, - createTintedIconManager = createTintedIconManager, - createBatteryMeterViewController = createBatteryMeterViewController, - statusBarIconController = statusBarIconController, - ) + } + Spacer(modifier = Modifier.height(16.dp)) + // This view has its own horizontal padding + QuickSettings( + modifier = Modifier.sysuiResTag("expanded_qs_scroll_view"), + viewModel.qsSceneAdapter, + ) + } + } + AnimatedVisibility( + visible = !isCustomizing, + modifier = Modifier.align(Alignment.CenterHorizontally).fillMaxWidth() + ) { + QuickSettingsTheme { + // This view has its own horizontal padding + // TODO(b/321716470) This should use a lifecycle tied to the scene. + FooterActions( + viewModel = footerActionsViewModel, + qsVisibilityLifecycleOwner = lifecycleOwner, + modifier = Modifier.element(QuickSettings.Elements.FooterActions) + ) } - Spacer(modifier = Modifier.height(16.dp)) - QuickSettings( - modifier = Modifier.fillMaxHeight(), - viewModel.qsSceneAdapter, - ) } } HeadsUpNotificationSpace( diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsTheme.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsTheme.kt new file mode 100644 index 000000000000..87b6f95b0ae6 --- /dev/null +++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsTheme.kt @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.qs.ui.composable + +import android.view.ContextThemeWrapper +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.remember +import androidx.compose.ui.platform.LocalContext +import com.android.systemui.res.R + +@Composable +fun QuickSettingsTheme(content: @Composable () -> Unit) { + val context = LocalContext.current + val themedContext = + remember(context) { ContextThemeWrapper(context, R.style.Theme_SystemUI_QuickSettings) } + CompositionLocalProvider(LocalContext provides themedContext) { content() } +} diff --git a/packages/SystemUI/customization/Android.bp b/packages/SystemUI/customization/Android.bp index 1d1849680040..81b5bd43bdbd 100644 --- a/packages/SystemUI/customization/Android.bp +++ b/packages/SystemUI/customization/Android.bp @@ -34,15 +34,19 @@ android_library { "PluginCoreLib", "SystemUIPluginLib", "SystemUIUnfoldLib", - "androidx.dynamicanimation_dynamicanimation", + "kotlinx_coroutines", + "dagger2", + "jsr330", + ], + libs: [ + // Keep android-specific libraries as libs instead of static_libs, so that they don't break + // things when included as transitive dependencies in robolectric targets. "androidx.concurrent_concurrent-futures", + "androidx.dynamicanimation_dynamicanimation", "androidx.lifecycle_lifecycle-runtime-ktx", "androidx.lifecycle_lifecycle-viewmodel-ktx", "androidx.recyclerview_recyclerview", "kotlinx_coroutines_android", - "kotlinx_coroutines", - "dagger2", - "jsr330", ], resource_dirs: [ "res", diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AnimatableClockView.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AnimatableClockView.kt index 2bfa7d9bbd7b..cea49e1b535e 100644 --- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AnimatableClockView.kt +++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AnimatableClockView.kt @@ -27,6 +27,7 @@ import android.text.TextUtils import android.text.format.DateFormat import android.util.AttributeSet import android.util.MathUtils.constrainedMap +import android.view.View import android.widget.TextView import com.android.app.animation.Interpolators import com.android.internal.annotations.VisibleForTesting @@ -51,7 +52,7 @@ class AnimatableClockView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0, - defStyleRes: Int = 0 + defStyleRes: Int = 0, ) : TextView(context, attrs, defStyleAttr, defStyleRes) { // To protect us from issues from this being null while the TextView constructor is running, we // implement the get method and ensure a value is returned before initialization is complete. @@ -61,6 +62,9 @@ class AnimatableClockView @JvmOverloads constructor( get() = logger.buffer set(value) { logger = Logger(value, TAG) } + var hasCustomPositionUpdatedAnimation: Boolean = false + var migratedClocks: Boolean = false + private val time = Calendar.getInstance() private val dozingWeightInternal: Int @@ -193,9 +197,18 @@ class AnimatableClockView @JvmOverloads constructor( } else { animator.updateLayout(layout) } + if (migratedClocks && hasCustomPositionUpdatedAnimation) { + // Expand width to avoid clock being clipped during stepping animation + setMeasuredDimension(measuredWidth + + MeasureSpec.getSize(widthMeasureSpec) / 2, measuredHeight) + } } override fun onDraw(canvas: Canvas) { + if (migratedClocks && hasCustomPositionUpdatedAnimation) { + canvas.save() + canvas.translate((parent as View).measuredWidth / 4F, 0F) + } logger.d({ "onDraw($str1)"}) { str1 = text.toString() } // Use textAnimator to render text if animation is enabled. // Otherwise default to using standard draw functions. @@ -205,6 +218,9 @@ class AnimatableClockView @JvmOverloads constructor( } else { super.onDraw(canvas) } + if (migratedClocks && hasCustomPositionUpdatedAnimation) { + canvas.restore() + } } override fun invalidate() { diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt index 99d321695d04..001e3a5fc911 100644 --- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt +++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt @@ -193,6 +193,8 @@ class DefaultClockController( ClockFaceConfig(hasCustomPositionUpdatedAnimation = hasStepClockAnimation) init { + view.migratedClocks = migratedClocks + view.hasCustomPositionUpdatedAnimation = hasStepClockAnimation animations = LargeClockAnimations(view, 0f, 0f) } diff --git a/packages/SystemUI/docs/scene.md b/packages/SystemUI/docs/scene.md index 715d16015402..105e4385bb25 100644 --- a/packages/SystemUI/docs/scene.md +++ b/packages/SystemUI/docs/scene.md @@ -98,12 +98,16 @@ file evalutes to `true`. $ adb shell cmd statusbar echo -b SceneFramework:verbose -# Look for the log statements from the framework: +### Checking if the framework is enabled + +Look for the log statements from the framework: ```console $ adb logcat -v time SceneFramework:* *:S ``` +### Disabling the framework + To **disable** the framework, simply turn off the main aconfig flag: ```console @@ -112,6 +116,11 @@ $ adb shell device_config put systemui com.android.systemui.scene_container fals ## Defining a scene +By default, the framework ships with fully functional scenes as enumarated +[here](https://cs.android.com/android/platform/superproject/main/+/main:frameworks/base/packages/SystemUI/src/com/android/systemui/scene/shared/model/SceneKey.kt). +Should a variant owner or OEM want to replace or add a new scene, they could +do so by defining their own scene. This section describes how to do that. + Each scene is defined as an implementation of the [`ComposableScene`](https://cs.android.com/android/platform/superproject/main/+/main:frameworks/base/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/ComposableScene.kt) interface, which has three parts: 1. The `key` property returns the @@ -305,3 +314,52 @@ top-level Dagger module at this puts together the scenes from `SceneModule`, the configuration from `SceneContainerConfigModule`, and the startable from `SceneContainerStartableModule`. + +## Integration Notes + +### Relationship to Jetpack Compose + +The scene framework depends on Jetpack Compose; therefore, compiling System UI with +Jetpack Compose is required. However, because Jetpack Compose and Android Views +[interoperate](https://developer.android.com/jetpack/compose/migrate/interoperability-apis/views-in-compose), +the UI in each scene doesn't necessarily need to be a pure hierarchy of `@Composable` +functions; instead, it's acceptable to use an `AndroidView` somewhere in the +hierarchy of composable functions to include a `View` or `ViewGroup` subtree. + +#### Interoperability with Views +The scene framework comes with built-in functionality to animate the entire scene and/or +elements within the scene in-tandem with the actual scene transition progress. + +For example, as the user drags their finger down rom the top of the lockscreen, +the shade scene becomes visible and gradually expands, the amount of expansion tracks +the movement of the finger. + +That feature of the framework uses a custom `element(ElementKey)` Jetpack Compose +`Modifier` to refer to elements within a scene. +The transition builders then use the same `ElementKey` objects to refer to those elements +and describe how they animate in-tandem with scene transitions. Because this is a +Jetpack Compose `Modifier`, it means that, in order for an element in a scene to be +animated automatically by the framework, that element must be nested within a pure +`@Composable` hierarchy. The element itself is allowed to be a classic Android `View` +(nested within a Jetpack Compose `AndroidView`) but all ancestors must be `@Composable` +functions. + +### Notifications + +As of January 2024, the integration of notifications and heads-up notifications (HUNs) +into the scene framework follows an unusual pattern. We chose this pattern due to migration +risk and performance concerns but will eventually replace it with the more common element +placement pattern that all other elements are following. + +The special pattern for notifications is that, instead of the notification list +(`NotificationStackScrollLayout` or "NSSL", which also displays HUNs) being placed in the element +hierarchy within the scenes that display notifications, the NSSL (which continues to be an Android View) +"floats" above the scene container, rendering on top of everything. This is very similar to +how NSSL is integrated with the legacy shade, prior to the scene framework. + +In order to render the NSSL as if it's part of the organic hierarchy of elements within its +scenes, we control the NSSL's self-imposed effective bounds (e.g. position offsets, clip path, +size) from `@Composable` elements within the normal scene hierarchy. These special +"placeholder" elements can be found +[here](https://cs.android.com/android/platform/superproject/main/+/main:frameworks/base/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt). + diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/domain/interactor/FingerprintPropertyInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/domain/interactor/FingerprintPropertyInteractorTest.kt index ccf119ab3088..97c407cb9b16 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/domain/interactor/FingerprintPropertyInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/domain/interactor/FingerprintPropertyInteractorTest.kt @@ -41,10 +41,10 @@ import org.junit.runner.RunWith class FingerprintPropertyInteractorTest : SysuiTestCase() { private val kosmos = testKosmos() private val testScope = kosmos.testScope - private val underTest = kosmos.fingerprintPropertyInteractor - private val repository = kosmos.fingerprintPropertyRepository - private val configurationRepository = kosmos.fakeConfigurationRepository - private val displayRepository = kosmos.displayRepository + private val underTest by lazy { kosmos.fingerprintPropertyInteractor } + private val repository by lazy { kosmos.fingerprintPropertyRepository } + private val configurationRepository by lazy { kosmos.fakeConfigurationRepository } + private val displayRepository by lazy { kosmos.displayRepository } @Test fun sensorLocation_resolution1f() = diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt index c8560c31cdf1..c300e0a905b6 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt @@ -55,7 +55,9 @@ class PrimaryBouncerInteractorWithCoroutinesTest : SysuiTestCase() { @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor @Mock private lateinit var mSelectedUserInteractor: SelectedUserInteractor @Mock private lateinit var faceAuthInteractor: DeviceEntryFaceAuthInteractor - private val mainHandler = FakeHandler(Looper.getMainLooper()) + private val mainHandler by lazy { + FakeHandler(Looper.getMainLooper()) + } private lateinit var underTest: PrimaryBouncerInteractor @Before diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModelTest.kt index 27b84b2ffabc..d30e33332926 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModelTest.kt @@ -39,8 +39,8 @@ class AuthMethodBouncerViewModelTest : SysuiTestCase() { private val kosmos = testKosmos() private val testScope = kosmos.testScope - private val bouncerInteractor = kosmos.bouncerInteractor - private val underTest = + private val bouncerInteractor by lazy { kosmos.bouncerInteractor } + private val underTest by lazy { PinBouncerViewModel( applicationContext = context, viewModelScope = testScope.backgroundScope, @@ -49,6 +49,7 @@ class AuthMethodBouncerViewModelTest : SysuiTestCase() { simBouncerInteractor = kosmos.simBouncerInteractor, authenticationMethod = AuthenticationMethodModel.Pin, ) + } @Test fun animateFailure() = diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt index cfe8c5d52c18..73db1757c06a 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt @@ -58,8 +58,8 @@ class BouncerViewModelTest : SysuiTestCase() { private val kosmos = testKosmos() private val testScope = kosmos.testScope - private val authenticationInteractor = kosmos.authenticationInteractor - private val bouncerInteractor = kosmos.bouncerInteractor + private val authenticationInteractor by lazy { kosmos.authenticationInteractor } + private val bouncerInteractor by lazy { kosmos.bouncerInteractor } private lateinit var underTest: BouncerViewModel @Before diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/KeyguardBouncerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/KeyguardBouncerViewModelTest.kt index a0c2acc31589..cddbd1f78dd5 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/KeyguardBouncerViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/KeyguardBouncerViewModelTest.kt @@ -66,7 +66,9 @@ class KeyguardBouncerViewModelTest : SysuiTestCase() { @Mock private lateinit var faceAuthInteractor: DeviceEntryFaceAuthInteractor lateinit var bouncerInteractor: PrimaryBouncerInteractor - private val mainHandler = FakeHandler(Looper.getMainLooper()) + private val mainHandler by lazy { + FakeHandler(Looper.getMainLooper()) + } val repository = FakeKeyguardBouncerRepository() lateinit var underTest: KeyguardBouncerViewModel diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt index b3b6457b46e7..c6d612d5dc79 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt @@ -52,17 +52,18 @@ class PasswordBouncerViewModelTest : SysuiTestCase() { private val kosmos = testKosmos() private val testScope = kosmos.testScope private val authenticationInteractor = kosmos.authenticationInteractor - private val sceneInteractor = kosmos.sceneInteractor - private val bouncerInteractor = kosmos.bouncerInteractor - private val bouncerViewModel = kosmos.bouncerViewModel + private val sceneInteractor by lazy { kosmos.sceneInteractor } + private val bouncerInteractor by lazy { kosmos.bouncerInteractor } + private val bouncerViewModel by lazy { kosmos.bouncerViewModel } private val isInputEnabled = MutableStateFlow(true) - private val underTest = + private val underTest by lazy { PasswordBouncerViewModel( viewModelScope = testScope.backgroundScope, interactor = bouncerInteractor, isInputEnabled.asStateFlow(), ) + } @Before fun setUp() { diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt index c2680bcc82a3..725bdbd43445 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt @@ -53,17 +53,18 @@ class PatternBouncerViewModelTest : SysuiTestCase() { private val kosmos = testKosmos() private val testScope = kosmos.testScope - private val authenticationInteractor = kosmos.authenticationInteractor - private val sceneInteractor = kosmos.sceneInteractor - private val bouncerInteractor = kosmos.bouncerInteractor - private val bouncerViewModel = kosmos.bouncerViewModel - private val underTest = + private val authenticationInteractor by lazy { kosmos.authenticationInteractor } + private val sceneInteractor by lazy { kosmos.sceneInteractor } + private val bouncerInteractor by lazy { kosmos.bouncerInteractor } + private val bouncerViewModel by lazy { kosmos.bouncerViewModel } + private val underTest by lazy { PatternBouncerViewModel( applicationContext = context, viewModelScope = testScope.backgroundScope, interactor = bouncerInteractor, isInputEnabled = MutableStateFlow(true).asStateFlow(), ) + } private val containerSize = 90 // px private val dotSize = 30 // px diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt index 1d660d63710d..06e12586d384 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt @@ -53,22 +53,24 @@ class PinBouncerViewModelTest : SysuiTestCase() { private val kosmos = testKosmos() private val testScope = kosmos.testScope - private val sceneInteractor = kosmos.sceneInteractor - private val authenticationInteractor = kosmos.authenticationInteractor - private val bouncerInteractor = kosmos.bouncerInteractor - private val bouncerViewModel = kosmos.bouncerViewModel - private val underTest = - PinBouncerViewModel( - applicationContext = context, - viewModelScope = testScope.backgroundScope, - interactor = bouncerInteractor, - isInputEnabled = MutableStateFlow(true).asStateFlow(), - simBouncerInteractor = kosmos.simBouncerInteractor, - authenticationMethod = AuthenticationMethodModel.Pin, - ) + private val sceneInteractor by lazy { kosmos.sceneInteractor } + private val authenticationInteractor by lazy { kosmos.authenticationInteractor } + private val bouncerInteractor by lazy { kosmos.bouncerInteractor } + private val bouncerViewModel by lazy { kosmos.bouncerViewModel } + private lateinit var underTest: PinBouncerViewModel @Before fun setUp() { + underTest = + PinBouncerViewModel( + applicationContext = context, + viewModelScope = testScope.backgroundScope, + interactor = bouncerInteractor, + isInputEnabled = MutableStateFlow(true).asStateFlow(), + simBouncerInteractor = kosmos.simBouncerInteractor, + authenticationMethod = AuthenticationMethodModel.Pin, + ) + overrideResource(R.string.keyguard_enter_your_pin, ENTER_YOUR_PIN) overrideResource(R.string.kg_wrong_pin, WRONG_PIN) } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorCommunalDisabledTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorCommunalDisabledTest.kt index ed29aa4ac202..e8216735fb5d 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorCommunalDisabledTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorCommunalDisabledTest.kt @@ -27,7 +27,6 @@ import com.android.systemui.communal.data.repository.fakeCommunalWidgetRepositor import com.android.systemui.coroutines.collectLastValue import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository -import com.android.systemui.keyguard.domain.interactor.communalInteractor import com.android.systemui.kosmos.testScope import com.android.systemui.testKosmos import com.google.common.truth.Truth.assertThat diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt index 7769223c8af2..86279ef24ca7 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt @@ -18,6 +18,7 @@ package com.android.systemui.communal.domain.interactor import android.app.smartspace.SmartspaceTarget +import android.content.pm.UserInfo import android.provider.Settings.Secure.HUB_MODE_TUTORIAL_COMPLETED import android.widget.RemoteViews import androidx.test.ext.junit.runners.AndroidJUnit4 @@ -42,12 +43,12 @@ import com.android.systemui.communal.widgets.EditWidgetsActivityStarter import com.android.systemui.coroutines.collectLastValue import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository -import com.android.systemui.keyguard.domain.interactor.communalInteractor -import com.android.systemui.keyguard.domain.interactor.editWidgetsActivityStarter import com.android.systemui.kosmos.testScope import com.android.systemui.smartspace.data.repository.FakeSmartspaceRepository import com.android.systemui.smartspace.data.repository.fakeSmartspaceRepository import com.android.systemui.testKosmos +import com.android.systemui.user.data.repository.FakeUserRepository +import com.android.systemui.user.data.repository.fakeUserRepository import com.android.systemui.util.mockito.mock import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat @@ -59,8 +60,10 @@ import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test import org.junit.runner.RunWith +import org.mockito.Mock import org.mockito.Mockito.mock import org.mockito.Mockito.verify +import org.mockito.MockitoAnnotations /** * This class of test cases assume that communal is enabled. For disabled cases, see @@ -70,6 +73,9 @@ import org.mockito.Mockito.verify @OptIn(ExperimentalCoroutinesApi::class) @RunWith(AndroidJUnit4::class) class CommunalInteractorTest : SysuiTestCase() { + @Mock private lateinit var mainUser: UserInfo + @Mock private lateinit var secondaryUser: UserInfo + private val kosmos = testKosmos() private val testScope = kosmos.testScope @@ -78,6 +84,7 @@ class CommunalInteractorTest : SysuiTestCase() { private lateinit var mediaRepository: FakeCommunalMediaRepository private lateinit var widgetRepository: FakeCommunalWidgetRepository private lateinit var smartspaceRepository: FakeSmartspaceRepository + private lateinit var userRepository: FakeUserRepository private lateinit var keyguardRepository: FakeKeyguardRepository private lateinit var communalPrefsRepository: FakeCommunalPrefsRepository private lateinit var editWidgetsActivityStarter: EditWidgetsActivityStarter @@ -86,15 +93,22 @@ class CommunalInteractorTest : SysuiTestCase() { @Before fun setUp() { + MockitoAnnotations.initMocks(this) + tutorialRepository = kosmos.fakeCommunalTutorialRepository communalRepository = kosmos.fakeCommunalRepository mediaRepository = kosmos.fakeCommunalMediaRepository widgetRepository = kosmos.fakeCommunalWidgetRepository smartspaceRepository = kosmos.fakeSmartspaceRepository + userRepository = kosmos.fakeUserRepository keyguardRepository = kosmos.fakeKeyguardRepository editWidgetsActivityStarter = kosmos.editWidgetsActivityStarter communalPrefsRepository = kosmos.fakeCommunalPrefsRepository + whenever(mainUser.isMain).thenReturn(true) + whenever(secondaryUser.isMain).thenReturn(false) + userRepository.setUserInfos(listOf(mainUser, secondaryUser)) + underTest = kosmos.communalInteractor } @@ -103,36 +117,52 @@ class CommunalInteractorTest : SysuiTestCase() { testScope.runTest { assertThat(underTest.isCommunalEnabled).isTrue() } @Test - fun isCommunalAvailable_trueWhenStorageUnlock() = + fun isCommunalAvailable_storageUnlockedAndMainUser_true() = testScope.runTest { val isAvailable by collectLastValue(underTest.isCommunalAvailable) assertThat(isAvailable).isFalse() keyguardRepository.setIsEncryptedOrLockdown(false) + userRepository.setSelectedUserInfo(mainUser) runCurrent() assertThat(isAvailable).isTrue() } @Test - fun isCommunalAvailable_whenStorageUnlock_true() = + fun isCommunalAvailable_storageLockedAndMainUser_false() = + testScope.runTest { + val isAvailable by collectLastValue(underTest.isCommunalAvailable) + assertThat(isAvailable).isFalse() + + keyguardRepository.setIsEncryptedOrLockdown(true) + userRepository.setSelectedUserInfo(mainUser) + runCurrent() + + assertThat(isAvailable).isFalse() + } + + @Test + fun isCommunalAvailable_storageUnlockedAndSecondaryUser_false() = testScope.runTest { val isAvailable by collectLastValue(underTest.isCommunalAvailable) assertThat(isAvailable).isFalse() keyguardRepository.setIsEncryptedOrLockdown(false) + userRepository.setSelectedUserInfo(secondaryUser) runCurrent() - assertThat(isAvailable).isTrue() + assertThat(isAvailable).isFalse() } @Test - fun updateAppWidgetHostActive_uponStorageUnlock_true() = + fun updateAppWidgetHostActive_uponStorageUnlockAsMainUser_true() = testScope.runTest { collectLastValue(underTest.isCommunalAvailable) assertThat(widgetRepository.isHostActive()).isFalse() keyguardRepository.setIsEncryptedOrLockdown(false) + userRepository.setSelectedUserInfo(mainUser) runCurrent() assertThat(widgetRepository.isHostActive()).isTrue() @@ -557,6 +587,43 @@ class CommunalInteractorTest : SysuiTestCase() { } @Test + fun isIdleOnCommunal() = + testScope.runTest { + val transitionState = + MutableStateFlow<ObservableCommunalTransitionState>( + ObservableCommunalTransitionState.Idle(CommunalSceneKey.Blank) + ) + communalRepository.setTransitionState(transitionState) + + // isIdleOnCommunal is false when not on communal. + val isIdleOnCommunal by collectLastValue(underTest.isIdleOnCommunal) + runCurrent() + assertThat(isIdleOnCommunal).isEqualTo(false) + + // Transition to communal. + transitionState.value = + ObservableCommunalTransitionState.Idle(CommunalSceneKey.Communal) + runCurrent() + + // isIdleOnCommunal is now true since we're on communal. + assertThat(isIdleOnCommunal).isEqualTo(true) + + // Start transition away from communal. + transitionState.value = + ObservableCommunalTransitionState.Transition( + fromScene = CommunalSceneKey.Communal, + toScene = CommunalSceneKey.Blank, + progress = flowOf(0f), + isInitiatedByUserInput = false, + isUserInputOngoing = flowOf(false), + ) + runCurrent() + + // isIdleOnCommunal turns false as soon as transition away starts. + assertThat(isIdleOnCommunal).isEqualTo(false) + } + + @Test fun testShowWidgetEditorStartsActivity() = testScope.runTest { underTest.showWidgetEditor() diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalTutorialInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalTutorialInteractorTest.kt index 9a3129f2e962..352463f5a198 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalTutorialInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalTutorialInteractorTest.kt @@ -16,6 +16,7 @@ package com.android.systemui.communal.domain.interactor +import android.content.pm.UserInfo import android.provider.Settings.Secure.HUB_MODE_TUTORIAL_COMPLETED import android.provider.Settings.Secure.HUB_MODE_TUTORIAL_NOT_STARTED import android.provider.Settings.Secure.HUB_MODE_TUTORIAL_STARTED @@ -24,13 +25,17 @@ import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.communal.data.repository.FakeCommunalRepository import com.android.systemui.communal.data.repository.FakeCommunalTutorialRepository +import com.android.systemui.communal.data.repository.fakeCommunalRepository +import com.android.systemui.communal.data.repository.fakeCommunalTutorialRepository import com.android.systemui.coroutines.collectLastValue import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository -import com.android.systemui.settings.UserTracker -import com.android.systemui.util.mockito.mock +import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository +import com.android.systemui.kosmos.testScope +import com.android.systemui.testKosmos +import com.android.systemui.user.data.repository.FakeUserRepository +import com.android.systemui.user.data.repository.fakeUserRepository import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat -import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test @@ -41,35 +46,36 @@ import org.mockito.MockitoAnnotations @SmallTest @RunWith(AndroidJUnit4::class) class CommunalTutorialInteractorTest : SysuiTestCase() { + @Mock lateinit var user: UserInfo - @Mock private lateinit var userTracker: UserTracker + private val kosmos = testKosmos() + private val testScope = kosmos.testScope - private lateinit var testScope: TestScope private lateinit var underTest: CommunalTutorialInteractor private lateinit var keyguardRepository: FakeKeyguardRepository private lateinit var communalTutorialRepository: FakeCommunalTutorialRepository private lateinit var communalRepository: FakeCommunalRepository + private lateinit var communalInteractor: CommunalInteractor + private lateinit var userRepository: FakeUserRepository @Before fun setUp() { MockitoAnnotations.initMocks(this) - testScope = TestScope() + keyguardRepository = kosmos.fakeKeyguardRepository + communalTutorialRepository = kosmos.fakeCommunalTutorialRepository + communalRepository = kosmos.fakeCommunalRepository + communalInteractor = kosmos.communalInteractor + userRepository = kosmos.fakeUserRepository - val withDeps = CommunalTutorialInteractorFactory.create(testScope) - keyguardRepository = withDeps.keyguardRepository - communalTutorialRepository = withDeps.communalTutorialRepository - communalRepository = withDeps.communalRepository - - underTest = withDeps.communalTutorialInteractor - - whenever(userTracker.userHandle).thenReturn(mock()) + underTest = kosmos.communalTutorialInteractor } @Test fun tutorialUnavailable_whenKeyguardNotVisible() = testScope.runTest { val isTutorialAvailable by collectLastValue(underTest.isTutorialAvailable) + setCommunalAvailable(true) communalTutorialRepository.setTutorialSettingState(HUB_MODE_TUTORIAL_NOT_STARTED) keyguardRepository.setKeyguardShowing(false) assertThat(isTutorialAvailable).isFalse() @@ -79,6 +85,7 @@ class CommunalTutorialInteractorTest : SysuiTestCase() { fun tutorialUnavailable_whenTutorialIsCompleted() = testScope.runTest { val isTutorialAvailable by collectLastValue(underTest.isTutorialAvailable) + setCommunalAvailable(true) keyguardRepository.setKeyguardShowing(true) keyguardRepository.setKeyguardOccluded(false) communalRepository.setIsCommunalHubShowing(false) @@ -87,9 +94,20 @@ class CommunalTutorialInteractorTest : SysuiTestCase() { } @Test + fun tutorialUnavailable_whenCommunalNotAvailable() = + testScope.runTest { + val isTutorialAvailable by collectLastValue(underTest.isTutorialAvailable) + setCommunalAvailable(false) + communalTutorialRepository.setTutorialSettingState(HUB_MODE_TUTORIAL_NOT_STARTED) + keyguardRepository.setKeyguardShowing(true) + assertThat(isTutorialAvailable).isFalse() + } + + @Test fun tutorialAvailable_whenTutorialNotStarted() = testScope.runTest { val isTutorialAvailable by collectLastValue(underTest.isTutorialAvailable) + setCommunalAvailable(true) keyguardRepository.setKeyguardShowing(true) keyguardRepository.setKeyguardOccluded(false) communalRepository.setIsCommunalHubShowing(false) @@ -101,6 +119,7 @@ class CommunalTutorialInteractorTest : SysuiTestCase() { fun tutorialAvailable_whenTutorialIsStarted() = testScope.runTest { val isTutorialAvailable by collectLastValue(underTest.isTutorialAvailable) + setCommunalAvailable(true) keyguardRepository.setKeyguardShowing(true) keyguardRepository.setKeyguardOccluded(false) communalRepository.setIsCommunalHubShowing(true) @@ -181,4 +200,16 @@ class CommunalTutorialInteractorTest : SysuiTestCase() { assertThat(tutorialSettingState).isEqualTo(HUB_MODE_TUTORIAL_COMPLETED) } + + private suspend fun setCommunalAvailable(available: Boolean) { + if (available) { + communalRepository.setIsCommunalEnabled(true) + keyguardRepository.setIsEncryptedOrLockdown(false) + whenever(user.isMain).thenReturn(true) + userRepository.setUserInfos(listOf(user)) + userRepository.setSelectedUserInfo(user) + } else { + keyguardRepository.setIsEncryptedOrLockdown(true) + } + } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/log/CommunalLoggerStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/log/CommunalLoggerStartableTest.kt index 721fc4906aba..6b1b93777fbc 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/log/CommunalLoggerStartableTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/log/CommunalLoggerStartableTest.kt @@ -21,14 +21,15 @@ import androidx.test.filters.SmallTest import com.android.internal.logging.UiEventLogger import com.android.systemui.SysuiTestCase import com.android.systemui.communal.domain.interactor.CommunalInteractor -import com.android.systemui.communal.domain.interactor.CommunalInteractorFactory +import com.android.systemui.communal.domain.interactor.communalInteractor import com.android.systemui.communal.shared.log.CommunalUiEvent import com.android.systemui.communal.shared.model.CommunalSceneKey import com.android.systemui.communal.shared.model.ObservableCommunalTransitionState +import com.android.systemui.kosmos.testScope +import com.android.systemui.testKosmos import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.emptyFlow -import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Before @@ -47,17 +48,16 @@ import org.mockito.MockitoAnnotations class CommunalLoggerStartableTest : SysuiTestCase() { @Mock private lateinit var uiEventLogger: UiEventLogger - private lateinit var testScope: TestScope + private val kosmos = testKosmos() + private val testScope = kosmos.testScope + private lateinit var communalInteractor: CommunalInteractor private lateinit var underTest: CommunalLoggerStartable @Before fun setUp() { MockitoAnnotations.initMocks(this) - - val withDeps = CommunalInteractorFactory.create() - testScope = withDeps.testScope - communalInteractor = withDeps.communalInteractor + communalInteractor = kosmos.communalInteractor underTest = CommunalLoggerStartable( diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/widgets/CommunalAppWidgetHostTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/widgets/CommunalAppWidgetHostTest.kt index e904236f8c3e..3aa99c40bd67 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/widgets/CommunalAppWidgetHostTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/widgets/CommunalAppWidgetHostTest.kt @@ -16,44 +16,52 @@ package com.android.systemui.communal.ui.widgets +import android.testing.TestableLooper +import android.testing.TestableLooper.RunWithLooper import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.communal.widgets.CommunalAppWidgetHost import com.android.systemui.communal.widgets.CommunalAppWidgetHostView -import com.android.systemui.kosmos.testScope -import com.android.systemui.testKosmos +import com.android.systemui.util.mockito.mock import com.google.common.truth.Truth.assertThat -import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @SmallTest +@RunWithLooper(setAsMainLooper = true) @RunWith(AndroidJUnit4::class) class CommunalAppWidgetHostTest : SysuiTestCase() { - private val kosmos = testKosmos() - private val testScope = kosmos.testScope + private lateinit var testableLooper: TestableLooper private lateinit var underTest: CommunalAppWidgetHost @Before fun setUp() { - underTest = CommunalAppWidgetHost(context = context, hostId = 116) + testableLooper = TestableLooper.get(this) + underTest = + CommunalAppWidgetHost( + context = context, + hostId = 116, + interactionHandler = mock(), + looper = testableLooper.looper + ) } @Test - fun createViewForCommunal_returnCommunalAppWidgetView() = - testScope.runTest { - val appWidgetId = 789 - val view = - underTest.createViewForCommunal( - context = context, - appWidgetId = appWidgetId, - appWidget = null - ) - assertThat(view).isInstanceOf(CommunalAppWidgetHostView::class.java) - assertThat(view).isNotNull() - assertThat(view.appWidgetId).isEqualTo(appWidgetId) - } + fun createViewForCommunal_returnCommunalAppWidgetView() { + val appWidgetId = 789 + val view = + underTest.createViewForCommunal( + context = context, + appWidgetId = appWidgetId, + appWidget = null + ) + testableLooper.processAllMessages() + + assertThat(view).isInstanceOf(CommunalAppWidgetHostView::class.java) + assertThat(view).isNotNull() + assertThat(view.appWidgetId).isEqualTo(appWidgetId) + } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalEditModeViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalEditModeViewModelTest.kt index 125ede413784..a2dec5ff8830 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalEditModeViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalEditModeViewModelTest.kt @@ -24,24 +24,25 @@ import androidx.test.filters.SmallTest import com.android.internal.logging.UiEventLogger import com.android.systemui.SysuiTestCase import com.android.systemui.communal.data.repository.FakeCommunalMediaRepository -import com.android.systemui.communal.data.repository.FakeCommunalRepository import com.android.systemui.communal.data.repository.FakeCommunalTutorialRepository import com.android.systemui.communal.data.repository.FakeCommunalWidgetRepository -import com.android.systemui.communal.domain.interactor.CommunalInteractorFactory +import com.android.systemui.communal.data.repository.fakeCommunalMediaRepository +import com.android.systemui.communal.data.repository.fakeCommunalTutorialRepository +import com.android.systemui.communal.data.repository.fakeCommunalWidgetRepository +import com.android.systemui.communal.domain.interactor.communalInteractor import com.android.systemui.communal.domain.model.CommunalContentModel import com.android.systemui.communal.shared.log.CommunalUiEvent import com.android.systemui.communal.shared.model.CommunalWidgetContentModel import com.android.systemui.communal.ui.viewmodel.CommunalEditModeViewModel import com.android.systemui.coroutines.collectLastValue -import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository import com.android.systemui.kosmos.testScope import com.android.systemui.media.controls.ui.MediaHost import com.android.systemui.smartspace.data.repository.FakeSmartspaceRepository +import com.android.systemui.smartspace.data.repository.fakeSmartspaceRepository import com.android.systemui.testKosmos import com.android.systemui.util.mockito.mock import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat -import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test @@ -51,7 +52,6 @@ import org.mockito.Mockito import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations -@OptIn(ExperimentalCoroutinesApi::class) @SmallTest @RunWith(AndroidJUnit4::class) class CommunalEditModeViewModelTest : SysuiTestCase() { @@ -61,8 +61,6 @@ class CommunalEditModeViewModelTest : SysuiTestCase() { private val kosmos = testKosmos() private val testScope = kosmos.testScope - private lateinit var keyguardRepository: FakeKeyguardRepository - private lateinit var communalRepository: FakeCommunalRepository private lateinit var tutorialRepository: FakeCommunalTutorialRepository private lateinit var widgetRepository: FakeCommunalWidgetRepository private lateinit var smartspaceRepository: FakeSmartspaceRepository @@ -74,17 +72,14 @@ class CommunalEditModeViewModelTest : SysuiTestCase() { fun setUp() { MockitoAnnotations.initMocks(this) - val withDeps = CommunalInteractorFactory.create(testScope) - keyguardRepository = withDeps.keyguardRepository - communalRepository = withDeps.communalRepository - tutorialRepository = withDeps.tutorialRepository - widgetRepository = withDeps.widgetRepository - smartspaceRepository = withDeps.smartspaceRepository - mediaRepository = withDeps.mediaRepository + tutorialRepository = kosmos.fakeCommunalTutorialRepository + widgetRepository = kosmos.fakeCommunalWidgetRepository + smartspaceRepository = kosmos.fakeSmartspaceRepository + mediaRepository = kosmos.fakeCommunalMediaRepository underTest = CommunalEditModeViewModel( - withDeps.communalInteractor, + kosmos.communalInteractor, mediaHost, uiEventLogger, ) @@ -134,19 +129,6 @@ class CommunalEditModeViewModelTest : SysuiTestCase() { } @Test - fun interactionHandlerIgnoresClicks() { - val interactionHandler = underTest.getInteractionHandler() - assertThat( - interactionHandler.onInteraction( - /* view = */ mock(), - /* pendingIntent = */ mock(), - /* response = */ mock() - ) - ) - .isEqualTo(false) - } - - @Test fun reorderWidget_uiEventLogging_start() { underTest.onReorderWidgetStart() verify(uiEventLogger).log(CommunalUiEvent.COMMUNAL_HUB_REORDER_WIDGET_START) diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt index f9cfc3732a01..c814f3f1db6a 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt @@ -17,32 +17,39 @@ package com.android.systemui.communal.view.viewmodel import android.app.smartspace.SmartspaceTarget +import android.content.pm.UserInfo import android.provider.Settings import android.widget.RemoteViews import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.communal.data.repository.FakeCommunalMediaRepository -import com.android.systemui.communal.data.repository.FakeCommunalPrefsRepository -import com.android.systemui.communal.data.repository.FakeCommunalRepository import com.android.systemui.communal.data.repository.FakeCommunalTutorialRepository import com.android.systemui.communal.data.repository.FakeCommunalWidgetRepository -import com.android.systemui.communal.domain.interactor.CommunalInteractorFactory +import com.android.systemui.communal.data.repository.fakeCommunalMediaRepository +import com.android.systemui.communal.data.repository.fakeCommunalTutorialRepository +import com.android.systemui.communal.data.repository.fakeCommunalWidgetRepository +import com.android.systemui.communal.domain.interactor.communalInteractor +import com.android.systemui.communal.domain.interactor.communalTutorialInteractor import com.android.systemui.communal.domain.model.CommunalContentModel import com.android.systemui.communal.shared.model.CommunalWidgetContentModel import com.android.systemui.communal.ui.viewmodel.CommunalViewModel import com.android.systemui.communal.ui.viewmodel.CommunalViewModel.Companion.POPUP_AUTO_HIDE_TIMEOUT_MS -import com.android.systemui.communal.widgets.WidgetInteractionHandler import com.android.systemui.coroutines.collectLastValue import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository +import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository +import com.android.systemui.kosmos.testScope import com.android.systemui.media.controls.ui.MediaHierarchyManager import com.android.systemui.media.controls.ui.MediaHost import com.android.systemui.smartspace.data.repository.FakeSmartspaceRepository +import com.android.systemui.smartspace.data.repository.fakeSmartspaceRepository +import com.android.systemui.testKosmos +import com.android.systemui.user.data.repository.FakeUserRepository +import com.android.systemui.user.data.repository.fakeUserRepository import com.android.systemui.util.mockito.mock import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.advanceTimeBy import kotlinx.coroutines.test.runTest import org.junit.Before @@ -58,16 +65,17 @@ import org.mockito.MockitoAnnotations @RunWith(AndroidJUnit4::class) class CommunalViewModelTest : SysuiTestCase() { @Mock private lateinit var mediaHost: MediaHost + @Mock private lateinit var user: UserInfo - private lateinit var testScope: TestScope + private val kosmos = testKosmos() + private val testScope = kosmos.testScope private lateinit var keyguardRepository: FakeKeyguardRepository - private lateinit var communalRepository: FakeCommunalRepository private lateinit var tutorialRepository: FakeCommunalTutorialRepository private lateinit var widgetRepository: FakeCommunalWidgetRepository private lateinit var smartspaceRepository: FakeSmartspaceRepository private lateinit var mediaRepository: FakeCommunalMediaRepository - private lateinit var communalPrefsRepository: FakeCommunalPrefsRepository + private lateinit var userRepository: FakeUserRepository private lateinit var underTest: CommunalViewModel @@ -75,23 +83,18 @@ class CommunalViewModelTest : SysuiTestCase() { fun setUp() { MockitoAnnotations.initMocks(this) - testScope = TestScope() - - val withDeps = CommunalInteractorFactory.create() - keyguardRepository = withDeps.keyguardRepository - communalRepository = withDeps.communalRepository - tutorialRepository = withDeps.tutorialRepository - widgetRepository = withDeps.widgetRepository - smartspaceRepository = withDeps.smartspaceRepository - mediaRepository = withDeps.mediaRepository - communalPrefsRepository = withDeps.communalPrefsRepository + keyguardRepository = kosmos.fakeKeyguardRepository + tutorialRepository = kosmos.fakeCommunalTutorialRepository + widgetRepository = kosmos.fakeCommunalWidgetRepository + smartspaceRepository = kosmos.fakeSmartspaceRepository + mediaRepository = kosmos.fakeCommunalMediaRepository + userRepository = kosmos.fakeUserRepository underTest = CommunalViewModel( testScope, - withDeps.communalInteractor, - WidgetInteractionHandler(mock()), - withDeps.tutorialInteractor, + kosmos.communalInteractor, + kosmos.communalTutorialInteractor, mediaHost, ) } @@ -106,9 +109,11 @@ class CommunalViewModelTest : SysuiTestCase() { @Test fun tutorial_tutorialNotCompletedAndKeyguardVisible_showTutorialContent() = testScope.runTest { - // Keyguard showing, and tutorial not started. + // Keyguard showing, storage unlocked, main user, and tutorial not started. keyguardRepository.setKeyguardShowing(true) keyguardRepository.setKeyguardOccluded(false) + keyguardRepository.setIsEncryptedOrLockdown(false) + setIsMainUser(true) tutorialRepository.setTutorialSettingState( Settings.Secure.HUB_MODE_TUTORIAL_NOT_STARTED ) @@ -204,4 +209,10 @@ class CommunalViewModelTest : SysuiTestCase() { underTest.onHidePopupAfterDismissCta() assertThat(isPopupOnDismissCtaShowing).isEqualTo(false) } + + private suspend fun setIsMainUser(isMainUser: Boolean) { + whenever(user.isMain).thenReturn(isMainUser) + userRepository.setUserInfos(listOf(user)) + userRepository.setSelectedUserInfo(user) + } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/widgets/WidgetInteractionHandlerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/widgets/WidgetInteractionHandlerTest.kt new file mode 100644 index 000000000000..69ff5ab3d84d --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/widgets/WidgetInteractionHandlerTest.kt @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.communal.widgets + +import android.app.PendingIntent +import android.content.Intent +import android.view.View +import android.widget.FrameLayout +import android.widget.RemoteViews.RemoteResponse +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.plugins.ActivityStarter +import com.android.systemui.util.mockito.eq +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mock +import org.mockito.Mockito.isNull +import org.mockito.Mockito.notNull +import org.mockito.Mockito.verify +import org.mockito.MockitoAnnotations + +@SmallTest +@RunWith(AndroidJUnit4::class) +class WidgetInteractionHandlerTest : SysuiTestCase() { + @Mock private lateinit var activityStarter: ActivityStarter + + private lateinit var underTest: WidgetInteractionHandler + + private val testIntent = + PendingIntent.getActivity( + context, + /* requestCode = */ 0, + Intent("action"), + PendingIntent.FLAG_IMMUTABLE + ) + private val testResponse = RemoteResponse.fromPendingIntent(testIntent) + + @Before + fun setUp() { + MockitoAnnotations.initMocks(this) + underTest = WidgetInteractionHandler(activityStarter) + } + + @Test + fun launchAnimatorIsUsedForWidgetView() { + val parent = FrameLayout(context) + val view = CommunalAppWidgetHostView(context) + parent.addView(view) + + underTest.onInteraction(view, testIntent, testResponse) + + verify(activityStarter) + .startPendingIntentMaybeDismissingKeyguard( + eq(testIntent), + isNull(), + notNull(), + ) + } + + @Test + fun launchAnimatorIsNotUsedForRegularView() { + val parent = FrameLayout(context) + val view = View(context) + parent.addView(view) + + underTest.onInteraction(view, testIntent, testResponse) + + verify(activityStarter) + .startPendingIntentMaybeDismissingKeyguard(eq(testIntent), isNull(), isNull()) + } +} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorTest.kt index 52305b1f5212..05b589126b08 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorTest.kt @@ -49,10 +49,10 @@ class DeviceEntryInteractorTest : SysuiTestCase() { private val kosmos = testKosmos() private val testScope = kosmos.testScope - private val faceAuthRepository = kosmos.fakeDeviceEntryFaceAuthRepository - private val trustRepository = kosmos.fakeTrustRepository - private val sceneInteractor = kosmos.sceneInteractor - private val authenticationInteractor = kosmos.authenticationInteractor + private val faceAuthRepository by lazy { kosmos.fakeDeviceEntryFaceAuthRepository } + private val trustRepository by lazy { kosmos.fakeTrustRepository } + private val sceneInteractor by lazy { kosmos.sceneInteractor } + private val authenticationInteractor by lazy { kosmos.authenticationInteractor } private lateinit var underTest: DeviceEntryInteractor @Before diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java index 562f96c28b19..c14346899ede 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java @@ -93,7 +93,7 @@ public class DreamOverlayServiceTest extends SysuiTestCase { @Rule public final LeakCheckedTest.SysuiLeakCheck mLeakCheck = new LeakCheckedTest.SysuiLeakCheck(); - WindowManager.LayoutParams mWindowParams = new WindowManager.LayoutParams(); + WindowManager.LayoutParams mWindowParams; @Mock IDreamOverlayCallback mDreamOverlayCallback; @@ -184,6 +184,7 @@ public class DreamOverlayServiceTest extends SysuiTestCase { when(mDreamOverlayContainerViewController.getContainerView()) .thenReturn(mDreamOverlayContainerView); + mWindowParams = new WindowManager.LayoutParams(); mService = new DreamOverlayService( mContext, mLifecycleOwner, diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/slider/SeekableSliderHapticPluginTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/slider/SeekableSliderHapticPluginTest.kt new file mode 100644 index 000000000000..ea766f8ea9bb --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/slider/SeekableSliderHapticPluginTest.kt @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.haptics.slider + +import android.widget.SeekBar +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.kosmos.testScope +import com.android.systemui.statusbar.VibratorHelper +import com.android.systemui.util.mockito.whenever +import com.android.systemui.util.time.fakeSystemClock +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.UnconfinedTestDispatcher +import kotlinx.coroutines.test.advanceTimeBy +import kotlinx.coroutines.test.runTest +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.ArgumentMatchers.anyInt +import org.mockito.Mock +import org.mockito.junit.MockitoJUnit +import org.mockito.junit.MockitoRule + +@SmallTest +@RunWith(AndroidJUnit4::class) +@OptIn(ExperimentalCoroutinesApi::class) +class SeekableSliderHapticPluginTest : SysuiTestCase() { + + private val kosmos = Kosmos() + + @Rule @JvmField val mMockitoRule: MockitoRule = MockitoJUnit.rule() + @Mock private lateinit var vibratorHelper: VibratorHelper + private val seekBar = SeekBar(mContext) + private lateinit var plugin: SeekableSliderHapticPlugin + + @Before + fun setup() { + whenever(vibratorHelper.getPrimitiveDurations(anyInt())).thenReturn(intArrayOf(0)) + } + + @Test + fun start_beginsTrackingSlider() = runOnStartedPlugin { assertThat(plugin.isTracking).isTrue() } + + @Test + fun stop_stopsTrackingSlider() = runOnStartedPlugin { + // WHEN called to stop + plugin.stop() + + // THEN stops tracking + assertThat(plugin.isTracking).isFalse() + } + + @Test + fun start_afterStop_startsTheTrackingAgain() = runOnStartedPlugin { + // WHEN the plugin is restarted + plugin.stop() + plugin.start() + + // THEN the tracking begins again + assertThat(plugin.isTracking).isTrue() + } + + @Test + fun onKeyDown_startsWaiting() = runOnStartedPlugin { + // WHEN a keyDown event is recorded + plugin.onKeyDown() + + // THEN the timer starts waiting + assertThat(plugin.isKeyUpTimerWaiting).isTrue() + } + + @Test + fun keyUpWaitComplete_triggersOnArrowUp() = runOnStartedPlugin { + // GIVEN an onKeyDown that starts the wait and a program progress change that advances the + // slider state to ARROW_HANDLE_MOVED_ONCE + plugin.onKeyDown() + plugin.onProgressChanged(seekBar, 50, false) + testScheduler.runCurrent() + assertThat(plugin.trackerState).isEqualTo(SliderState.ARROW_HANDLE_MOVED_ONCE) + + // WHEN the key-up wait completes after the timeout plus a small buffer + advanceTimeBy(KEY_UP_TIMEOUT + 10L) + + // THEN the onArrowUp event is delivered causing the slider tracker to move to IDLE + assertThat(plugin.trackerState).isEqualTo(SliderState.IDLE) + assertThat(plugin.isKeyUpTimerWaiting).isFalse() + } + + @Test + fun onKeyDown_whileWaiting_restartsWait() = runOnStartedPlugin { + // GIVEN an onKeyDown that starts the wait and a program progress change that advances the + // slider state to ARROW_HANDLE_MOVED_ONCE + plugin.onKeyDown() + plugin.onProgressChanged(seekBar, 50, false) + testScheduler.runCurrent() + assertThat(plugin.trackerState).isEqualTo(SliderState.ARROW_HANDLE_MOVED_ONCE) + + // WHEN half the timeout period has elapsed and a new keyDown event occurs + advanceTimeBy(KEY_UP_TIMEOUT / 2) + plugin.onKeyDown() + + // AFTER advancing by a period of time that should have complete the original wait + advanceTimeBy(KEY_UP_TIMEOUT / 2 + 10L) + + // THEN the timer is still waiting and the slider tracker remains on ARROW_HANDLE_MOVED_ONCE + assertThat(plugin.isKeyUpTimerWaiting).isTrue() + assertThat(plugin.trackerState).isEqualTo(SliderState.ARROW_HANDLE_MOVED_ONCE) + } + + private fun runOnStartedPlugin(test: suspend TestScope.() -> Unit) = + with(kosmos) { + testScope.runTest { + createPlugin(this, UnconfinedTestDispatcher(testScheduler)) + // GIVEN that the plugin is started + plugin.start() + + // THEN run the test + test() + } + } + + private fun createPlugin(scope: CoroutineScope, dispatcher: CoroutineDispatcher) { + plugin = + SeekableSliderHapticPlugin( + vibratorHelper, + kosmos.fakeSystemClock, + dispatcher, + scope, + ) + } + + companion object { + private const val KEY_UP_TIMEOUT = 100L + } +} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt index 6f62afc560fe..dc8b97abbfe8 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt @@ -139,6 +139,18 @@ class KeyguardRepositoryImplTest : SysuiTestCase() { } @Test + fun topClippingBounds() = + testScope.runTest { + assertThat(underTest.topClippingBounds.value).isNull() + + underTest.topClippingBounds.value = 50 + assertThat(underTest.topClippingBounds.value).isEqualTo(50) + + underTest.topClippingBounds.value = 500 + assertThat(underTest.topClippingBounds.value).isEqualTo(500) + } + + @Test fun clockPosition() = testScope.runTest { assertThat(underTest.clockPosition.value).isEqualTo(Position(0, 0)) diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt index 2c3afb1b40a9..0b320a28b419 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt @@ -54,15 +54,17 @@ class KeyguardInteractorTest : SysuiTestCase() { private val kosmos = testKosmos() private val testScope = kosmos.testScope - private val repository = kosmos.fakeKeyguardRepository - private val sceneInteractor = kosmos.sceneInteractor - private val commandQueue = FakeCommandQueue() + private val repository by lazy { kosmos.fakeKeyguardRepository } + private val sceneInteractor by lazy { kosmos.sceneInteractor } + private val commandQueue by lazy { + FakeCommandQueue() + } private val bouncerRepository = FakeKeyguardBouncerRepository() private val shadeRepository = FakeShadeRepository() private val transitionState: MutableStateFlow<ObservableTransitionState> = MutableStateFlow(ObservableTransitionState.Idle(SceneKey.Gone)) - private val underTest = + private val underTest by lazy { KeyguardInteractor( repository = repository, commandQueue = commandQueue, @@ -73,6 +75,7 @@ class KeyguardInteractorTest : SysuiTestCase() { shadeRepository = shadeRepository, sceneInteractorProvider = { sceneInteractor }, ) + } @Before fun setUp() { diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractorTest.kt index 9bccf4e26e87..ce43d4e14cc1 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractorTest.kt @@ -38,12 +38,12 @@ import org.junit.Assert.assertEquals import org.junit.Before import org.junit.Test import org.junit.runner.RunWith +import org.mockito.Mockito import org.mockito.Mockito.anyBoolean import org.mockito.Mockito.never import org.mockito.Mockito.reset import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations -import org.mockito.Spy @SmallTest @OptIn(ExperimentalCoroutinesApi::class) @@ -51,16 +51,19 @@ import org.mockito.Spy class LightRevealScrimInteractorTest : SysuiTestCase() { private val fakeKeyguardTransitionRepository = FakeKeyguardTransitionRepository() - @Spy private val fakeLightRevealScrimRepository = FakeLightRevealScrimRepository() + private val fakeLightRevealScrimRepository by lazy { + Mockito.spy(FakeLightRevealScrimRepository()) + } private val testScope = TestScope() - private val keyguardTransitionInteractor = + private val keyguardTransitionInteractor by lazy { KeyguardTransitionInteractorFactory.create( scope = testScope.backgroundScope, repository = fakeKeyguardTransitionRepository, ) .keyguardTransitionInteractor + } private lateinit var underTest: LightRevealScrimInteractor diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToAodTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToAodTransitionViewModelTest.kt index 9daf1860ebb8..199ffa6b87bd 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToAodTransitionViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToAodTransitionViewModelTest.kt @@ -20,11 +20,14 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.biometrics.data.repository.fingerprintPropertyRepository +import com.android.systemui.biometrics.data.repository.FakeFingerprintPropertyRepository import com.android.systemui.biometrics.shared.model.FingerprintSensorType import com.android.systemui.biometrics.shared.model.SensorStrength import com.android.systemui.coroutines.collectValues import com.android.systemui.keyguard.data.repository.biometricSettingsRepository import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository +import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository +import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.shared.model.KeyguardState.AOD import com.android.systemui.keyguard.shared.model.TransitionState @@ -36,6 +39,7 @@ import com.google.common.collect.Range import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runTest +import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -45,10 +49,18 @@ import org.junit.runner.RunWith class AlternateBouncerToAodTransitionViewModelTest : SysuiTestCase() { private val kosmos = testKosmos() private val testScope = kosmos.testScope - private val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository - private val fingerprintPropertyRepository = kosmos.fingerprintPropertyRepository - private val biometricSettingsRepository = kosmos.biometricSettingsRepository - private val underTest = kosmos.alternateBouncerToAodTransitionViewModel + private lateinit var keyguardTransitionRepository: FakeKeyguardTransitionRepository + private lateinit var fingerprintPropertyRepository: FakeFingerprintPropertyRepository + private lateinit var biometricSettingsRepository: FakeBiometricSettingsRepository + private lateinit var underTest: AlternateBouncerToAodTransitionViewModel + + @Before + fun setUp() { + keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository + fingerprintPropertyRepository = kosmos.fingerprintPropertyRepository + biometricSettingsRepository = kosmos.biometricSettingsRepository + underTest = kosmos.alternateBouncerToAodTransitionViewModel + } @Test fun deviceEntryParentViewAppear() = diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToGoneTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToGoneTransitionViewModelTest.kt index 3f7e0df427c6..d4438516a023 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToGoneTransitionViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToGoneTransitionViewModelTest.kt @@ -49,7 +49,9 @@ class AlternateBouncerToGoneTransitionViewModelTest : SysuiTestCase() { } private val testScope = kosmos.testScope private val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository - private val underTest = kosmos.alternateBouncerToGoneTransitionViewModel + private val underTest by lazy { + kosmos.alternateBouncerToGoneTransitionViewModel + } @Test fun deviceEntryParentViewDisappear() = diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToPrimaryBouncerTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToPrimaryBouncerTransitionViewModelTest.kt index c7ab52974852..ff41ea25f470 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToPrimaryBouncerTransitionViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToPrimaryBouncerTransitionViewModelTest.kt @@ -47,8 +47,8 @@ class AlternateBouncerToPrimaryBouncerTransitionViewModelTest : SysuiTestCase() } } private val testScope = kosmos.testScope - private val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository - private val underTest = kosmos.alternateBouncerToPrimaryBouncerTransitionViewModel + private val keyguardTransitionRepository by lazy { kosmos.fakeKeyguardTransitionRepository } + private val underTest by lazy { kosmos.alternateBouncerToPrimaryBouncerTransitionViewModel } @Test fun deviceEntryParentViewDisappear() = diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModelTest.kt index f1690dafe75a..89e29cf14451 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModelTest.kt @@ -20,10 +20,12 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.biometrics.data.repository.fingerprintPropertyRepository +import com.android.systemui.biometrics.data.repository.FakeFingerprintPropertyRepository import com.android.systemui.biometrics.shared.model.FingerprintSensorType import com.android.systemui.biometrics.shared.model.SensorStrength import com.android.systemui.coroutines.collectValues import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository +import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository import com.android.systemui.keyguard.shared.model.KeyguardState.AOD import com.android.systemui.keyguard.shared.model.KeyguardState.DOZING import com.android.systemui.keyguard.shared.model.KeyguardState.DREAMING @@ -41,6 +43,7 @@ import com.google.common.collect.Range import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runTest +import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -50,9 +53,16 @@ import org.junit.runner.RunWith class DreamingToLockscreenTransitionViewModelTest : SysuiTestCase() { private val kosmos = testKosmos() private val testScope = kosmos.testScope - private val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository - private val fingerprintPropertyRepository = kosmos.fingerprintPropertyRepository - private val underTest = kosmos.dreamingToLockscreenTransitionViewModel + private lateinit var keyguardTransitionRepository: FakeKeyguardTransitionRepository + private lateinit var fingerprintPropertyRepository: FakeFingerprintPropertyRepository + private lateinit var underTest: DreamingToLockscreenTransitionViewModel + + @Before + fun setUp() { + keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository + fingerprintPropertyRepository = kosmos.fingerprintPropertyRepository + underTest = kosmos.dreamingToLockscreenTransitionViewModel + } @Test fun shortcutsAlpha_bothShortcutsReceiveLastValue() = diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDreamingTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDreamingTransitionViewModelTest.kt index f763a6790b51..36b26a490fdb 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDreamingTransitionViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/GoneToDreamingTransitionViewModelTest.kt @@ -21,6 +21,7 @@ import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectValues import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository +import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.shared.model.TransitionState import com.android.systemui.keyguard.shared.model.TransitionStep @@ -29,6 +30,7 @@ import com.android.systemui.testKosmos import com.google.common.collect.Range import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.test.runTest +import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -37,8 +39,14 @@ import org.junit.runner.RunWith class GoneToDreamingTransitionViewModelTest : SysuiTestCase() { private val kosmos = testKosmos() private val testScope = kosmos.testScope - private val repository = kosmos.fakeKeyguardTransitionRepository - private val underTest = kosmos.goneToDreamingTransitionViewModel + private lateinit var repository: FakeKeyguardTransitionRepository + private lateinit var underTest: GoneToDreamingTransitionViewModel + + @Before + fun setUp() { + repository = kosmos.fakeKeyguardTransitionRepository + underTest = kosmos.goneToDreamingTransitionViewModel + } @Test fun runTest() = diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt index fd2fd2f04cde..6cc680baf938 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt @@ -25,9 +25,14 @@ import androidx.test.filters.SmallTest import com.android.systemui.Flags as AConfigFlags import com.android.systemui.Flags.FLAG_NEW_AOD_TRANSITION import com.android.systemui.SysuiTestCase +import com.android.systemui.communal.data.repository.communalRepository +import com.android.systemui.communal.shared.model.CommunalSceneKey +import com.android.systemui.communal.shared.model.ObservableCommunalTransitionState import com.android.systemui.coroutines.collectLastValue import com.android.systemui.deviceentry.data.repository.fakeDeviceEntryRepository +import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository +import com.android.systemui.keyguard.domain.interactor.keyguardInteractor import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.shared.model.TransitionState import com.android.systemui.keyguard.shared.model.TransitionStep @@ -42,6 +47,7 @@ import com.android.systemui.util.ui.stopAnimating import com.android.systemui.util.ui.value import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Before @@ -54,11 +60,14 @@ class KeyguardRootViewModelTest : SysuiTestCase() { private val kosmos = testKosmos() private val testScope = kosmos.testScope private val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository + private val keyguardInteractor = kosmos.keyguardInteractor + private val keyguardRepository = kosmos.fakeKeyguardRepository + private val communalRepository = kosmos.communalRepository private val screenOffAnimationController = kosmos.screenOffAnimationController private val deviceEntryRepository = kosmos.fakeDeviceEntryRepository private val notificationsKeyguardInteractor = kosmos.notificationsKeyguardInteractor private val dozeParameters = kosmos.dozeParameters - private val underTest = kosmos.keyguardRootViewModel + private val underTest by lazy { kosmos.keyguardRootViewModel } @Before fun setUp() { @@ -205,7 +214,38 @@ class KeyguardRootViewModelTest : SysuiTestCase() { } @Test - fun alpha_glanceableHubOpen_isZero() = + fun topClippingBounds() = + testScope.runTest { + val topClippingBounds by collectLastValue(underTest.topClippingBounds) + assertThat(topClippingBounds).isNull() + + keyguardRepository.topClippingBounds.value = 50 + assertThat(topClippingBounds).isEqualTo(50) + + keyguardRepository.topClippingBounds.value = 1000 + assertThat(topClippingBounds).isEqualTo(1000) + } + + @Test + fun alpha_idleOnHub_isZero() = + testScope.runTest { + val alpha by collectLastValue(underTest.alpha) + + // Hub transition state is idle with hub open. + communalRepository.setTransitionState( + flowOf(ObservableCommunalTransitionState.Idle(CommunalSceneKey.Communal)) + ) + runCurrent() + + // Set keyguard alpha to 1.0f. + keyguardInteractor.setAlpha(1.0f) + + // Alpha property remains 0 regardless. + assertThat(alpha).isEqualTo(0f) + } + + @Test + fun alpha_transitionToHub_isZero() = testScope.runTest { val alpha by collectLastValue(underTest.alpha) @@ -219,7 +259,7 @@ class KeyguardRootViewModelTest : SysuiTestCase() { } @Test - fun alpha_glanceableHubClosed_isOne() = + fun alpha_transitionFromHubToLockscreen_isOne() = testScope.runTest { val alpha by collectLastValue(underTest.alpha) diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt index aa15d0befa80..4595fbfab0d7 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt @@ -47,9 +47,11 @@ class LockscreenSceneViewModelTest : SysuiTestCase() { private val kosmos = testKosmos() private val testScope = kosmos.testScope - private val sceneInteractor = kosmos.sceneInteractor + private val sceneInteractor by lazy { kosmos.sceneInteractor } - private val underTest = createLockscreenSceneViewModel() + private val underTest by lazy { + createLockscreenSceneViewModel() + } @Test fun upTransitionSceneKey_canSwipeToUnlock_gone() = diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModelTest.kt index 74025fd6e100..8f04ec3814eb 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModelTest.kt @@ -27,18 +27,22 @@ import com.android.systemui.flags.Flags import com.android.systemui.flags.fakeFeatureFlagsClassic import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository +import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository +import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.shared.model.StatusBarState import com.android.systemui.keyguard.shared.model.TransitionState import com.android.systemui.keyguard.shared.model.TransitionStep import com.android.systemui.kosmos.testScope import com.android.systemui.shade.data.repository.shadeRepository +import com.android.systemui.shade.data.repository.ShadeRepository import com.android.systemui.testKosmos import com.google.common.collect.Range import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest +import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -51,10 +55,18 @@ class LockscreenToDreamingTransitionViewModelTest : SysuiTestCase() { fakeFeatureFlagsClassic.apply { set(Flags.FULL_SCREEN_USER_SWITCHER, false) } } private val testScope = kosmos.testScope - private val repository = kosmos.fakeKeyguardTransitionRepository - private val shadeRepository = kosmos.shadeRepository - private val keyguardRepository = kosmos.fakeKeyguardRepository - private val underTest = kosmos.lockscreenToDreamingTransitionViewModel + private lateinit var repository: FakeKeyguardTransitionRepository + private lateinit var shadeRepository: ShadeRepository + private lateinit var keyguardRepository: FakeKeyguardRepository + private lateinit var underTest: LockscreenToDreamingTransitionViewModel + + @Before + fun setUp() { + repository = kosmos.fakeKeyguardTransitionRepository + shadeRepository = kosmos.shadeRepository + keyguardRepository = kosmos.fakeKeyguardRepository + underTest = kosmos.lockscreenToDreamingTransitionViewModel + } @Test fun lockscreenFadeOut() = diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModelTest.kt index 6fcb0c11edad..b120f8776d9d 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModelTest.kt @@ -22,12 +22,15 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository +import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository import com.android.systemui.coroutines.collectLastValue import com.android.systemui.coroutines.collectValues import com.android.systemui.flags.Flags import com.android.systemui.flags.fakeFeatureFlagsClassic import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository +import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository +import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.shared.model.StatusBarState import com.android.systemui.keyguard.shared.model.TransitionState @@ -35,12 +38,14 @@ import com.android.systemui.keyguard.shared.model.TransitionStep import com.android.systemui.kosmos.testScope import com.android.systemui.res.R import com.android.systemui.shade.data.repository.shadeRepository +import com.android.systemui.shade.data.repository.ShadeRepository import com.android.systemui.testKosmos import com.google.common.collect.Range import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest +import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -52,11 +57,20 @@ class LockscreenToOccludedTransitionViewModelTest : SysuiTestCase() { fakeFeatureFlagsClassic.apply { set(Flags.FULL_SCREEN_USER_SWITCHER, false) } } private val testScope = kosmos.testScope - private val repository = kosmos.fakeKeyguardTransitionRepository - private val shadeRepository = kosmos.shadeRepository - private val keyguardRepository = kosmos.fakeKeyguardRepository - private val configurationRepository = kosmos.fakeConfigurationRepository - private val underTest = kosmos.lockscreenToOccludedTransitionViewModel + private lateinit var repository: FakeKeyguardTransitionRepository + private lateinit var shadeRepository: ShadeRepository + private lateinit var keyguardRepository: FakeKeyguardRepository + private lateinit var configurationRepository: FakeConfigurationRepository + private lateinit var underTest: LockscreenToOccludedTransitionViewModel + + @Before + fun setUp() { + repository = kosmos.fakeKeyguardTransitionRepository + shadeRepository = kosmos.shadeRepository + keyguardRepository = kosmos.fakeKeyguardRepository + configurationRepository = kosmos.fakeConfigurationRepository + underTest = kosmos.lockscreenToOccludedTransitionViewModel + } @Test fun lockscreenFadeOut() = diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelTest.kt index 639114c15000..dddf6485d0f4 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelTest.kt @@ -49,7 +49,9 @@ class OccludedToLockscreenTransitionViewModelTest : SysuiTestCase() { val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository val fingerprintPropertyRepository = kosmos.fingerprintPropertyRepository val configurationRepository = kosmos.fakeConfigurationRepository - val underTest = kosmos.occludedToLockscreenTransitionViewModel + val underTest by lazy { + kosmos.occludedToLockscreenTransitionViewModel + } @Test fun lockscreenFadeIn() = diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelTest.kt index 30b87bbbcf11..30ac34402ffd 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelTest.kt @@ -54,7 +54,9 @@ class PrimaryBouncerToGoneTransitionViewModelTest : SysuiTestCase() { val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository val primaryBouncerInteractor = kosmos.primaryBouncerInteractor val sysuiStatusBarStateController = kosmos.sysuiStatusBarStateController - val underTest = kosmos.primaryBouncerToGoneTransitionViewModel + val underTest by lazy { + kosmos.primaryBouncerToGoneTransitionViewModel + } @Before fun setUp() { diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/interactor/WorkProfileAutoAddedAfterRestoreTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/interactor/WorkProfileAutoAddedAfterRestoreTest.kt index 96d57743e2ee..4207a9c27ad0 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/interactor/WorkProfileAutoAddedAfterRestoreTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/pipeline/domain/interactor/WorkProfileAutoAddedAfterRestoreTest.kt @@ -54,7 +54,9 @@ import org.junit.runner.RunWith @OptIn(ExperimentalCoroutinesApi::class) class WorkProfileAutoAddedAfterRestoreTest : SysuiTestCase() { - private val kosmos = Kosmos().apply { fakeUserTracker.set(listOf(USER_0_INFO), 0) } + private val kosmos by lazy { + Kosmos().apply { fakeUserTracker.set(listOf(USER_0_INFO), 0) } + } // Getter here so it can change when there is a managed profile. private val workTileAvailable: Boolean get() = hasManagedProfile() diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/colorcorrection/domain/ColorCorrectionTileMapperTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/colorcorrection/domain/ColorCorrectionTileMapperTest.kt index 8ee6d2005350..d05e98faee22 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/colorcorrection/domain/ColorCorrectionTileMapperTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/colorcorrection/domain/ColorCorrectionTileMapperTest.kt @@ -36,8 +36,9 @@ import org.junit.runner.RunWith class ColorCorrectionTileMapperTest : SysuiTestCase() { private val kosmos = Kosmos() private val colorCorrectionTileConfig = kosmos.qsColorCorrectionTileConfig - private val subtitleArray = + private val subtitleArray by lazy { context.resources.getStringArray(R.array.tile_states_color_correction) + } // Using lazy (versus =) to make sure we override the right context -- see b/311612168 private val mapper by lazy { ColorCorrectionTileMapper( diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/custom/data/repository/CustomTileRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/custom/data/repository/CustomTileRepositoryTest.kt index a84b9fa32d85..da60c18dcfd7 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/custom/data/repository/CustomTileRepositoryTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/custom/data/repository/CustomTileRepositoryTest.kt @@ -308,21 +308,27 @@ class CustomTileRepositoryTest : SysuiTestCase() { val TEST_COMPONENT = ComponentName("test.pkg", "test.cls") val TEST_USER_1 = UserHandle.of(1)!! - val TEST_TILE_1 = + val TEST_TILE_1 by lazy { Tile().apply { label = "test_tile_1" icon = Icon.createWithContentUri("file://test_1") } + } val TEST_TILE_KEY_1 = TileServiceKey(TEST_COMPONENT, TEST_USER_1.identifier) - val TEST_DEFAULTS_1 = CustomTileDefaults.Result(TEST_TILE_1.icon, TEST_TILE_1.label) + val TEST_DEFAULTS_1 by lazy { + CustomTileDefaults.Result(TEST_TILE_1.icon, TEST_TILE_1.label) + } val TEST_USER_2 = UserHandle.of(2)!! - val TEST_TILE_2 = + val TEST_TILE_2 by lazy { Tile().apply { label = "test_tile_2" icon = Icon.createWithContentUri("file://test_2") } + } val TEST_TILE_KEY_2 = TileServiceKey(TEST_COMPONENT, TEST_USER_2.identifier) - val TEST_DEFAULTS_2 = CustomTileDefaults.Result(TEST_TILE_2.icon, TEST_TILE_2.label) + val TEST_DEFAULTS_2 by lazy { + CustomTileDefaults.Result(TEST_TILE_2.icon, TEST_TILE_2.label) + } } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/custom/domain/interactor/CustomTileInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/custom/domain/interactor/CustomTileInteractorTest.kt index 20653ca18efc..995d6ac66137 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/custom/domain/interactor/CustomTileInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/custom/domain/interactor/CustomTileInteractorTest.kt @@ -180,11 +180,14 @@ class CustomTileInteractorTest : SysuiTestCase() { val TEST_COMPONENT = ComponentName("test.pkg", "test.cls") val TEST_USER = UserHandle.of(1)!! - val TEST_TILE = + val TEST_TILE by lazy { Tile().apply { label = "test_tile_1" icon = Icon.createWithContentUri("file://test_1") } - val TEST_DEFAULTS = CustomTileDefaults.Result(TEST_TILE.icon, TEST_TILE.label) + } + val TEST_DEFAULTS by lazy { + CustomTileDefaults.Result(TEST_TILE.icon, TEST_TILE.label) + } } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/inversion/domain/ColorInversionTileMapperTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/inversion/domain/ColorInversionTileMapperTest.kt index f3c3579966fd..ccd7ed92b884 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/inversion/domain/ColorInversionTileMapperTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/inversion/domain/ColorInversionTileMapperTest.kt @@ -39,7 +39,9 @@ class ColorInversionTileMapperTest : SysuiTestCase() { private val colorInversionTileConfig = kosmos.qsColorInversionTileConfig private val subtitleArrayId = SubtitleArrayMapping.getSubtitleId(colorInversionTileConfig.tileSpec.spec) - private val subtitleArray = context.resources.getStringArray(subtitleArrayId) + private val subtitleArray by lazy { + context.resources.getStringArray(subtitleArrayId) + } // Using lazy (versus =) to make sure we override the right context -- see b/311612168 private val mapper by lazy { ColorInversionTileMapper( diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/uimodenight/domain/UiModeNightTileDataInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/uimodenight/domain/UiModeNightTileDataInteractorTest.kt index 7497ebdc2978..46e1609b02ad 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/uimodenight/domain/UiModeNightTileDataInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/uimodenight/domain/UiModeNightTileDataInteractorTest.kt @@ -53,8 +53,9 @@ import org.mockito.Mockito.verify @SmallTest @RunWith(AndroidJUnit4::class) class UiModeNightTileDataInteractorTest : SysuiTestCase() { - private val configurationController: ConfigurationController = + private val configurationController: ConfigurationController by lazy { ConfigurationControllerImpl(context) + } private val batteryController = FakeBatteryController(LeakCheck()) private val locationController = FakeLocationController(LeakCheck()) diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/adapter/QSSceneAdapterImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/adapter/QSSceneAdapterImplTest.kt index d9b1ea1aedcc..cae20d006dec 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/adapter/QSSceneAdapterImplTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/adapter/QSSceneAdapterImplTest.kt @@ -16,12 +16,16 @@ package com.android.systemui.qs.ui.adapter +import android.content.res.Configuration import android.os.Bundle +import android.view.Surface import android.view.View import androidx.asynclayoutinflater.view.AsyncLayoutInflater import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase +import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository +import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor import com.android.systemui.coroutines.collectLastValue import com.android.systemui.qs.QSImpl import com.android.systemui.qs.dagger.QSComponent @@ -34,6 +38,7 @@ import com.android.systemui.util.mockito.mock import com.android.systemui.util.mockito.nullable import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat +import java.util.Locale import javax.inject.Provider import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.StandardTestDispatcher @@ -81,11 +86,17 @@ class QSSceneAdapterImplTest : SysuiTestCase() { .also { components.add(it) } } } + private val configuration = Configuration(context.resources.configuration) + + private val fakeConfigurationRepository = + FakeConfigurationRepository().apply { onConfigurationChange(configuration) } + private val configurationInteractor = ConfigurationInteractor(fakeConfigurationRepository) private val mockAsyncLayoutInflater = mock<AsyncLayoutInflater>() { whenever(inflate(anyInt(), nullable(), any())).then { invocation -> val mockView = mock<View>() + whenever(mockView.context).thenReturn(context) invocation .getArgument<AsyncLayoutInflater.OnInflateFinishedListener>(2) .onInflateFinished( @@ -102,6 +113,7 @@ class QSSceneAdapterImplTest : SysuiTestCase() { qsImplProvider, testDispatcher, testScope.backgroundScope, + configurationInteractor, { mockAsyncLayoutInflater }, ) @@ -297,6 +309,9 @@ class QSSceneAdapterImplTest : SysuiTestCase() { @Test fun reinflation_previousStateDestroyed() = testScope.runTest { + // Run all flows... In particular, initial configuration propagation that could cause + // QSImpl to re-inflate. + runCurrent() val qsImpl by collectLastValue(underTest.qsImpl) underTest.inflate(context) @@ -322,4 +337,81 @@ class QSSceneAdapterImplTest : SysuiTestCase() { bundleArgCaptor.value, ) } + + @Test + fun changeInLocale_reinflation() = + testScope.runTest { + val qsImpl by collectLastValue(underTest.qsImpl) + + underTest.inflate(context) + runCurrent() + + val oldQsImpl = qsImpl!! + + val newLocale = + if (configuration.locales[0] == Locale("en-US")) { + Locale("es-UY") + } else { + Locale("en-US") + } + configuration.setLocale(newLocale) + fakeConfigurationRepository.onConfigurationChange(configuration) + runCurrent() + + assertThat(oldQsImpl).isNotSameInstanceAs(qsImpl!!) + } + + @Test + fun changeInFontSize_reinflation() = + testScope.runTest { + val qsImpl by collectLastValue(underTest.qsImpl) + + underTest.inflate(context) + runCurrent() + + val oldQsImpl = qsImpl!! + + configuration.fontScale *= 2 + fakeConfigurationRepository.onConfigurationChange(configuration) + runCurrent() + + assertThat(oldQsImpl).isNotSameInstanceAs(qsImpl!!) + } + + @Test + fun changeInAssetPath_reinflation() = + testScope.runTest { + val qsImpl by collectLastValue(underTest.qsImpl) + + underTest.inflate(context) + runCurrent() + + val oldQsImpl = qsImpl!! + + configuration.assetsSeq += 1 + fakeConfigurationRepository.onConfigurationChange(configuration) + runCurrent() + + assertThat(oldQsImpl).isNotSameInstanceAs(qsImpl!!) + } + + @Test + fun otherChangesInConfiguration_noReinflation_configurationChangeDispatched() = + testScope.runTest { + val qsImpl by collectLastValue(underTest.qsImpl) + + underTest.inflate(context) + runCurrent() + + val oldQsImpl = qsImpl!! + configuration.densityDpi *= 2 + configuration.windowConfiguration.maxBounds.scale(2f) + configuration.windowConfiguration.rotation = Surface.ROTATION_270 + fakeConfigurationRepository.onConfigurationChange(configuration) + runCurrent() + + assertThat(oldQsImpl).isSameInstanceAs(qsImpl!!) + verify(qsImpl!!).onConfigurationChanged(configuration) + verify(qsImpl!!.view).dispatchConfigurationChanged(configuration) + } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt index be523b813494..42200a3d33ec 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt @@ -23,6 +23,8 @@ import com.android.systemui.coroutines.collectLastValue import com.android.systemui.flags.FakeFeatureFlagsClassic import com.android.systemui.flags.Flags import com.android.systemui.kosmos.testScope +import com.android.systemui.qs.FooterActionsController +import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel import com.android.systemui.qs.ui.adapter.FakeQSSceneAdapter import com.android.systemui.scene.domain.interactor.sceneInteractor import com.android.systemui.scene.shared.model.Direction @@ -39,12 +41,16 @@ import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconsVi import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository import com.android.systemui.testKosmos +import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.mock +import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test import org.junit.runner.RunWith +import org.mockito.Mockito.times +import org.mockito.Mockito.verify @SmallTest @RunWith(AndroidJUnit4::class) @@ -52,10 +58,16 @@ class QuickSettingsSceneViewModelTest : SysuiTestCase() { private val kosmos = testKosmos() private val testScope = kosmos.testScope - private val sceneInteractor = kosmos.sceneInteractor + private val sceneInteractor by lazy { kosmos.sceneInteractor } private val mobileIconsInteractor = FakeMobileIconsInteractor(FakeMobileMappingsProxy(), mock()) private val flags = FakeFeatureFlagsClassic().also { it.set(Flags.NEW_NETWORK_SLICE_UI, false) } private val qsFlexiglassAdapter = FakeQSSceneAdapter { mock() } + private val footerActionsViewModel = mock<FooterActionsViewModel>() + private val footerActionsViewModelFactory = + mock<FooterActionsViewModel.Factory> { + whenever(create(any())).thenReturn(footerActionsViewModel) + } + private val footerActionsController = mock<FooterActionsController>() private var mobileIconsViewModel: MobileIconsViewModel = MobileIconsViewModel( @@ -94,6 +106,8 @@ class QuickSettingsSceneViewModelTest : SysuiTestCase() { shadeHeaderViewModel = shadeHeaderViewModel, qsSceneAdapter = qsFlexiglassAdapter, notifications = kosmos.notificationsPlaceholderViewModel, + footerActionsViewModelFactory, + footerActionsController, ) } @@ -125,4 +139,12 @@ class QuickSettingsSceneViewModelTest : SysuiTestCase() { ) ) } + + @Test + fun gettingViewModelInitializesControllerOnlyOnce() { + underTest.getFooterActionsViewModel(mock()) + underTest.getFooterActionsViewModel(mock()) + + verify(footerActionsController, times(1)).init() + } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt index 1cd764e01bad..1e5ebd0c2acd 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt @@ -123,30 +123,32 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() { private val kosmos = testKosmos().apply { fakeSceneContainerFlags.enabled = true } private val testScope = kosmos.testScope - private val sceneContainerConfig = kosmos.sceneContainerConfig - private val sceneInteractor = kosmos.sceneInteractor - private val authenticationInteractor = kosmos.authenticationInteractor - private val deviceEntryInteractor = kosmos.deviceEntryInteractor - private val communalInteractor = kosmos.communalInteractor + private val sceneContainerConfig by lazy { kosmos.sceneContainerConfig } + private val sceneInteractor by lazy { kosmos.sceneInteractor } + private val authenticationInteractor by lazy { kosmos.authenticationInteractor } + private val deviceEntryInteractor by lazy { kosmos.deviceEntryInteractor } + private val communalInteractor by lazy { kosmos.communalInteractor } - private val transitionState = + private val transitionState by lazy { MutableStateFlow<ObservableTransitionState>( ObservableTransitionState.Idle(sceneContainerConfig.initialSceneKey) ) - private val sceneContainerViewModel = + } + private val sceneContainerViewModel by lazy { SceneContainerViewModel( sceneInteractor = sceneInteractor, falsingInteractor = kosmos.falsingInteractor, ) .apply { setTransitionState(transitionState) } + } - private val bouncerInteractor = kosmos.bouncerInteractor + private val bouncerInteractor by lazy { kosmos.bouncerInteractor } private lateinit var mobileConnectionsRepository: FakeMobileConnectionsRepository private lateinit var bouncerActionButtonInteractor: BouncerActionButtonInteractor private lateinit var bouncerViewModel: BouncerViewModel - private val lockscreenSceneViewModel = + private val lockscreenSceneViewModel by lazy { LockscreenSceneViewModel( applicationScope = testScope.backgroundScope, deviceEntryInteractor = deviceEntryInteractor, @@ -157,6 +159,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() { ), notifications = kosmos.notificationsPlaceholderViewModel, ) + } private val mobileIconsInteractor = FakeMobileIconsInteractor(FakeMobileMappingsProxy(), mock()) @@ -179,8 +182,8 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() { private lateinit var shadeHeaderViewModel: ShadeHeaderViewModel private lateinit var shadeSceneViewModel: ShadeSceneViewModel - private val keyguardInteractor = kosmos.keyguardInteractor - private val powerInteractor = kosmos.powerInteractor + private val keyguardInteractor by lazy { kosmos.keyguardInteractor } + private val powerInteractor by lazy { kosmos.powerInteractor } private var bouncerSceneJob: Job? = null diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt index fc0df1288553..16cb6231a872 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt @@ -79,13 +79,13 @@ class SceneContainerStartableTest : SysuiTestCase() { private val kosmos = testKosmos() private val testScope = kosmos.testScope - private val sceneInteractor = kosmos.sceneInteractor - private val sceneContainerFlags = kosmos.fakeSceneContainerFlags - private val authenticationInteractor = kosmos.authenticationInteractor - private val bouncerInteractor = kosmos.bouncerInteractor - private val faceAuthRepository = kosmos.fakeDeviceEntryFaceAuthRepository - private val deviceEntryInteractor = kosmos.deviceEntryInteractor - private val keyguardInteractor = kosmos.keyguardInteractor + private val sceneInteractor by lazy { kosmos.sceneInteractor } + private val sceneContainerFlags by lazy { kosmos.fakeSceneContainerFlags } + private val authenticationInteractor by lazy { kosmos.authenticationInteractor } + private val bouncerInteractor by lazy { kosmos.bouncerInteractor } + private val faceAuthRepository by lazy { kosmos.fakeDeviceEntryFaceAuthRepository } + private val deviceEntryInteractor by lazy { kosmos.deviceEntryInteractor } + private val keyguardInteractor by lazy { kosmos.keyguardInteractor } private val sysUiState: SysUiState = mock() private val falsingCollector: FalsingCollector = mock() private val powerInteractor = PowerInteractorFactory.create().powerInteractor diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt index ede453d85ee1..a16ce4325dcf 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt @@ -41,7 +41,7 @@ import org.junit.runner.RunWith class SceneContainerViewModelTest : SysuiTestCase() { private val kosmos = testKosmos() - private val interactor = kosmos.sceneInteractor + private val interactor by lazy { kosmos.sceneInteractor } private lateinit var underTest: SceneContainerViewModel @Before diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModelTest.kt index 51745023c5be..e9a2a3befb03 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModelTest.kt @@ -35,7 +35,7 @@ import org.mockito.MockitoAnnotations class ShadeHeaderViewModelTest : SysuiTestCase() { private val kosmos = testKosmos() private val testScope = kosmos.testScope - private val sceneInteractor = kosmos.sceneInteractor + private val sceneInteractor by lazy { kosmos.sceneInteractor } private val mobileIconsInteractor = FakeMobileIconsInteractor(FakeMobileMappingsProxy(), mock()) private val flags = FakeFeatureFlagsClassic().also { it.set(Flags.NEW_NETWORK_SLICE_UI, false) } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt index 251daffe2d91..5ef095fd8201 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt @@ -60,8 +60,8 @@ class ShadeSceneViewModelTest : SysuiTestCase() { private val kosmos = testKosmos() private val testScope = kosmos.testScope - private val sceneInteractor = kosmos.sceneInteractor - private val deviceEntryInteractor = kosmos.deviceEntryInteractor + private val sceneInteractor by lazy { kosmos.sceneInteractor } + private val deviceEntryInteractor by lazy { kosmos.deviceEntryInteractor } private val mobileIconsInteractor = FakeMobileIconsInteractor(FakeMobileMappingsProxy(), mock()) private val flags = FakeFeatureFlagsClassic().also { it.set(Flags.NEW_NETWORK_SLICE_UI, false) } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/smartspace/CommunalSmartspaceControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/smartspace/CommunalSmartspaceControllerTest.kt index ef2046d85a14..ad4b98bdb3ee 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/smartspace/CommunalSmartspaceControllerTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/smartspace/CommunalSmartspaceControllerTest.kt @@ -69,7 +69,9 @@ class CommunalSmartspaceControllerTest : SysuiTestCase() { private lateinit var controller: CommunalSmartspaceController // TODO(b/272811280): Remove usage of real view - private val fakeParent = FrameLayout(context) + private val fakeParent by lazy { + FrameLayout(context) + } /** * A class which implements SmartspaceView and extends View. This is mocked to provide the right diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/smartspace/DreamSmartspaceControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/smartspace/DreamSmartspaceControllerTest.kt index e09385934991..3a386311223f 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/smartspace/DreamSmartspaceControllerTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/smartspace/DreamSmartspaceControllerTest.kt @@ -73,8 +73,9 @@ class DreamSmartspaceControllerTest : SysuiTestCase() { @Mock private lateinit var weatherViewComponent: SmartspaceViewComponent - @Spy - private var weatherSmartspaceView: SmartspaceView = TestView(context) + private val weatherSmartspaceView: SmartspaceView by lazy { + Mockito.spy(TestView(context)) + } @Mock private lateinit var targetFilter: SmartspaceTargetFilter @@ -88,8 +89,9 @@ class DreamSmartspaceControllerTest : SysuiTestCase() { @Mock private lateinit var precondition: SmartspacePrecondition - @Spy - private var smartspaceView: SmartspaceView = TestView(context) + private val smartspaceView: SmartspaceView by lazy { + Mockito.spy(TestView(context)) + } @Mock private lateinit var listener: BcSmartspaceDataPlugin.SmartspaceTargetListener @@ -100,7 +102,9 @@ class DreamSmartspaceControllerTest : SysuiTestCase() { private lateinit var controller: DreamSmartspaceController // TODO(b/272811280): Remove usage of real view - private val fakeParent = FrameLayout(context) + private val fakeParent by lazy { + FrameLayout(context) + } /** * A class which implements SmartspaceView and extends View. This is mocked to provide the right diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/NotificationStackAppearanceIntegrationTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/NotificationStackAppearanceIntegrationTest.kt index 607996d67d4f..6a2e31739c77 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/NotificationStackAppearanceIntegrationTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/NotificationStackAppearanceIntegrationTest.kt @@ -56,9 +56,9 @@ class NotificationStackAppearanceIntegrationTest : SysuiTestCase() { } } private val testScope = kosmos.testScope - private val placeholderViewModel = kosmos.notificationsPlaceholderViewModel - private val appearanceViewModel = kosmos.notificationStackAppearanceViewModel - private val sceneInteractor = kosmos.sceneInteractor + private val placeholderViewModel by lazy { kosmos.notificationsPlaceholderViewModel } + private val appearanceViewModel by lazy { kosmos.notificationStackAppearanceViewModel } + private val sceneInteractor by lazy { kosmos.sceneInteractor } @Test fun updateBounds() = diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/VolumeDialogController.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/VolumeDialogController.java index 3d9645a3d983..b1736b16875d 100644 --- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/VolumeDialogController.java +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/VolumeDialogController.java @@ -227,5 +227,10 @@ public interface VolumeDialogController { void onCaptionEnabledStateChanged(Boolean isEnabled, Boolean checkBeforeSwitch); // requires version 2 void onShowCsdWarning(@AudioManager.CsdWarning int csdWarning, int durationMs); + + /** + * Callback function for when the volume changed due to a physical key press. + */ + void onVolumeChangedFromKey(); } } diff --git a/packages/SystemUI/res-keyguard/values-af/strings.xml b/packages/SystemUI/res-keyguard/values-af/strings.xml index a6a81222a8cb..f801990e314e 100644 --- a/packages/SystemUI/res-keyguard/values-af/strings.xml +++ b/packages/SystemUI/res-keyguard/values-af/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laai tans"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laai tans vinnig"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laai tans stadig"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laaiproses word geoptimeer om battery te beskerm"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Kwessie met laaibykomstigheid"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Netwerk is gesluit"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Geen SIM nie"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"Onbruikbare SIM."</string> diff --git a/packages/SystemUI/res-keyguard/values-am/strings.xml b/packages/SystemUI/res-keyguard/values-am/strings.xml index fb84414c19df..356eebb074c2 100644 --- a/packages/SystemUI/res-keyguard/values-am/strings.xml +++ b/packages/SystemUI/res-keyguard/values-am/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ኃይል በመሙላት ላይ"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • በፍጥነት ኃይልን በመሙላት ላይ"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • በዝግታ ኃይልን በመሙላት ላይ"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ባትሪን ለመጠበቅ ኃይል መሙላት ተብቷል"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ተለዋዋጭን ኃይል በመሙላት ላይ ችግር"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"አውታረ መረብ ተቆልፏል"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"ምንም SIM የለም"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"ጥቅም ላይ የማይውል ሲም።"</string> diff --git a/packages/SystemUI/res-keyguard/values-ar/strings.xml b/packages/SystemUI/res-keyguard/values-ar/strings.xml index fb330929f4d3..707388e68aea 100644 --- a/packages/SystemUI/res-keyguard/values-ar/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ar/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • جارٍ الشحن"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • جارٍ الشحن سريعًا"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • جارٍ الشحن ببطء"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • تم تحسين الشحن لحماية البطارية"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • مشكلة متعلّقة بجهاز الشحن الملحق"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"الشبكة مؤمّنة"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"لا تتوفر شريحة SIM."</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"شريحة SIM غير قابلة للاستخدام."</string> diff --git a/packages/SystemUI/res-keyguard/values-as/strings.xml b/packages/SystemUI/res-keyguard/values-as/strings.xml index a123bb795708..8b9d30666aa2 100644 --- a/packages/SystemUI/res-keyguard/values-as/strings.xml +++ b/packages/SystemUI/res-keyguard/values-as/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • চ্চার্জ কৰি থকা হৈছে"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • দ্ৰুত গতিৰে চাৰ্জ কৰি থকা হৈছে"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • লাহে লাহে চাৰ্জ কৰি থকা হৈছে"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • বেটাৰী সুৰক্ষিত কৰিবলৈ চাৰ্জিং অপ্টিমাইজ কৰা হৈছে"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • চাৰ্জিঙৰ আনুষংগিক সামগ্ৰীত সমস্যা হৈছে"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"নেটৱর্ক লক কৰা অৱস্থাত আছে"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"কোনো ছিম নাই"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"ব্যৱহাৰ কৰিব নোৱৰা ছিম।"</string> diff --git a/packages/SystemUI/res-keyguard/values-az/strings.xml b/packages/SystemUI/res-keyguard/values-az/strings.xml index b133b30a657c..39d8032fb203 100644 --- a/packages/SystemUI/res-keyguard/values-az/strings.xml +++ b/packages/SystemUI/res-keyguard/values-az/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Enerji yığır"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Sürətlə enerji yığır"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Yavaş enerji yığır"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Batareyanı qorumaq üçün şarj optimallaşdırılıb"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Şarj aksesuarı ilə bağlı problem"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Şəbəkə kilidlidir"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"SIM yoxdur"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"İstifadəyə yararsız SIM."</string> diff --git a/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml b/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml index 9a919624c4fa..519e5f6cabd4 100644 --- a/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml +++ b/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Puni se"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Brzo se puni"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Sporo se puni"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Punjenje je optimizovano da bi se zaštitila baterija"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Problem sa dodatnim priborom za punjenje"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Mreža je zaključana"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Nema SIM-a"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"Neupotrebljiv SIM."</string> diff --git a/packages/SystemUI/res-keyguard/values-be/strings.xml b/packages/SystemUI/res-keyguard/values-be/strings.xml index 5e46b715c0e3..15bc616f7efb 100644 --- a/packages/SystemUI/res-keyguard/values-be/strings.xml +++ b/packages/SystemUI/res-keyguard/values-be/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ідзе зарадка"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ідзе хуткая зарадка"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ідзе павольная зарадка"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • У мэтах зберажэння акумулятара зарадка аптымізавана"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Праблема з зараднай прыладай"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Сетка заблакіравана"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Няма SIM-карты"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"Непрыдатная для выкарыстання SIM-карта."</string> diff --git a/packages/SystemUI/res-keyguard/values-bg/strings.xml b/packages/SystemUI/res-keyguard/values-bg/strings.xml index ab931ede75b0..7e2e2b3fa41b 100644 --- a/packages/SystemUI/res-keyguard/values-bg/strings.xml +++ b/packages/SystemUI/res-keyguard/values-bg/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарежда се"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарежда се бързо"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарежда се бавно"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зареждането е оптимизирано с цел запазване на батерията"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Проблем със зарядното устройство"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Мрежата е заключена"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Няма SIM карта"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"Неизползваема SIM карта."</string> diff --git a/packages/SystemUI/res-keyguard/values-bn/strings.xml b/packages/SystemUI/res-keyguard/values-bn/strings.xml index e25de9318f5d..2f7d3ba107cd 100644 --- a/packages/SystemUI/res-keyguard/values-bn/strings.xml +++ b/packages/SystemUI/res-keyguard/values-bn/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • চার্জ হচ্ছে"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • দ্রুত চার্জ হচ্ছে"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ধীরে চার্জ হচ্ছে"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ব্যাটারি ভাল রাখতে চার্জিং অপ্টিমাইজ করা হয়েছে"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • চার্জিং অ্যাক্সেসরিতে সমস্যা রয়েছে"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"নেটওয়ার্ক লক করা আছে"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"কোনও সিম নেই"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"ব্যবহারযোগ্য নয় এমন সিম।"</string> diff --git a/packages/SystemUI/res-keyguard/values-bs/strings.xml b/packages/SystemUI/res-keyguard/values-bs/strings.xml index cd7aaeb8117a..e35298b830ab 100644 --- a/packages/SystemUI/res-keyguard/values-bs/strings.xml +++ b/packages/SystemUI/res-keyguard/values-bs/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Punjenje"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Brzo punjenje"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Sporo punjenje"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Punjenje je optimizirano radi zaštite baterije"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Problem s opremom za punjenje"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Mreža je zaključana"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Nema SIM-a"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"Neupotrebljiv SIM."</string> diff --git a/packages/SystemUI/res-keyguard/values-ca/strings.xml b/packages/SystemUI/res-keyguard/values-ca/strings.xml index bf8a592c27b9..0fcc49103810 100644 --- a/packages/SystemUI/res-keyguard/values-ca/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ca/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • S\'està carregant"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • S\'està carregant ràpidament"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • S\'està carregant lentament"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Càrrega optimitzada per protegir la bateria"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Problema relacionat amb l\'accessori de càrrega"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"La xarxa està bloquejada"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"No hi ha cap SIM"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"La SIM no es pot utilitzar."</string> diff --git a/packages/SystemUI/res-keyguard/values-cs/strings.xml b/packages/SystemUI/res-keyguard/values-cs/strings.xml index bedafd8dd3b8..3764032b9c21 100644 --- a/packages/SystemUI/res-keyguard/values-cs/strings.xml +++ b/packages/SystemUI/res-keyguard/values-cs/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nabíjení"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Rychlé nabíjení"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Pomalé nabíjení"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimalizované nabíjení za účelem ochrany baterie"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Problém s nabíjecím příslušenstvím"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Síť je blokována"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Žádná SIM karta"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"SIM kartu nelze použít."</string> diff --git a/packages/SystemUI/res-keyguard/values-da/strings.xml b/packages/SystemUI/res-keyguard/values-da/strings.xml index 93f505e8bbf2..8b04c4636230 100644 --- a/packages/SystemUI/res-keyguard/values-da/strings.xml +++ b/packages/SystemUI/res-keyguard/values-da/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Oplader"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Oplader hurtigt"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Oplader langsomt"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Opladning er optimeret for at beskytte batteriet"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Problem med opladertilbehør"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Netværket er låst"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Intet SIM-kort"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"Deaktiveret SIM-kort."</string> diff --git a/packages/SystemUI/res-keyguard/values-de/strings.xml b/packages/SystemUI/res-keyguard/values-de/strings.xml index 01e166e36559..f122f4901d3c 100644 --- a/packages/SystemUI/res-keyguard/values-de/strings.xml +++ b/packages/SystemUI/res-keyguard/values-de/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Wird geladen"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Wird schnell geladen"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Wird langsam geladen"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimiertes Laden zur Akkuschonung"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Problem mit dem Ladezubehör"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Netzwerk gesperrt"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Keine SIM-Karte"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"SIM-Karte ist nicht nutzbar."</string> diff --git a/packages/SystemUI/res-keyguard/values-el/strings.xml b/packages/SystemUI/res-keyguard/values-el/strings.xml index 97692424cf2c..9c05a29dcdf6 100644 --- a/packages/SystemUI/res-keyguard/values-el/strings.xml +++ b/packages/SystemUI/res-keyguard/values-el/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Φόρτιση"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Γρήγορη φόρτιση"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Αργή φόρτιση"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Η φόρτιση βελτιστοποιήθηκε για την προστασία της μπαταρίας"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Πρόβλημα αξεσουάρ φόρτισης"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Κλειδωμένο δίκτυο"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Δεν υπάρχει SIM"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"Η SIM δεν μπορεί να χρησιμοποιηθεί."</string> diff --git a/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml b/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml index 087ab3a79358..fc8790c9902f 100644 --- a/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml +++ b/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging rapidly"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging slowly"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging optimised to protect battery"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Issue with charging accessory"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Network locked"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"No SIM"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"Unusable SIM."</string> diff --git a/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml b/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml index 7297cf929e2f..cb13fd578b7b 100644 --- a/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml +++ b/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml @@ -33,8 +33,8 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging rapidly"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging slowly"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging optimized to protect battery"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Issue with charging accessory"</string> + <string name="keyguard_plugged_in_charging_limited" msgid="5369697538556777542">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging on hold to protect battery"</string> + <string name="keyguard_plugged_in_incompatible_charger" msgid="6384203333154532125">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Check charging accessory"</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Network locked"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"No SIM"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"Unusable SIM."</string> diff --git a/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml b/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml index 087ab3a79358..fc8790c9902f 100644 --- a/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml +++ b/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging rapidly"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging slowly"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging optimised to protect battery"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Issue with charging accessory"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Network locked"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"No SIM"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"Unusable SIM."</string> diff --git a/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml b/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml index 087ab3a79358..fc8790c9902f 100644 --- a/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml +++ b/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging rapidly"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging slowly"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging optimised to protect battery"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Issue with charging accessory"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Network locked"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"No SIM"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"Unusable SIM."</string> diff --git a/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml b/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml index ead8bce626b8..188acd63e22a 100644 --- a/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml +++ b/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml @@ -33,8 +33,8 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging rapidly"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging slowly"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging optimized to protect battery"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Issue with charging accessory"</string> + <string name="keyguard_plugged_in_charging_limited" msgid="5369697538556777542">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging on hold to protect battery"</string> + <string name="keyguard_plugged_in_incompatible_charger" msgid="6384203333154532125">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Check charging accessory"</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Network locked"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"No SIM"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"Unusable SIM."</string> diff --git a/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml b/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml index 5b82c443ff62..3851b07143a2 100644 --- a/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml +++ b/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando rápidamente"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando lentamente"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carga optimizada para proteger la batería"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Problema con el accesorio de carga"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Bloqueada para la red"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"No hay ninguna tarjeta SIM"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"Tarjeta SIM inutilizable."</string> diff --git a/packages/SystemUI/res-keyguard/values-es/strings.xml b/packages/SystemUI/res-keyguard/values-es/strings.xml index cf7f3d220443..c0fccddef915 100644 --- a/packages/SystemUI/res-keyguard/values-es/strings.xml +++ b/packages/SystemUI/res-keyguard/values-es/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando rápidamente"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando lentamente"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carga optimizada para proteger la batería"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Problema con el accesorio de carga"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Bloqueada para la red"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"No hay ninguna SIM."</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"No se puede usar la SIM."</string> diff --git a/packages/SystemUI/res-keyguard/values-et/strings.xml b/packages/SystemUI/res-keyguard/values-et/strings.xml index 6335ca84c75d..5f75c87e5420 100644 --- a/packages/SystemUI/res-keyguard/values-et/strings.xml +++ b/packages/SystemUI/res-keyguard/values-et/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laadimine"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Kiirlaadimine"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Aeglane laadimine"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laadimine on aku kaitsmiseks optimeeritud"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • probleem laadimistarvikuga"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Võrk on lukus"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"SIM-i pole"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"SIM-i ei saa kasutada."</string> diff --git a/packages/SystemUI/res-keyguard/values-eu/strings.xml b/packages/SystemUI/res-keyguard/values-eu/strings.xml index b47c58a770aa..486531ac991d 100644 --- a/packages/SystemUI/res-keyguard/values-eu/strings.xml +++ b/packages/SystemUI/res-keyguard/values-eu/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Kargatzen"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Bizkor kargatzen"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mantso kargatzen"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Bateria ez kaltetzeko, kargatzeko modua optimizatu da"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Arazo bat dago kargatzeko osagarriarekin"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Sarea blokeatuta dago"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Ez dago SIMik"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"Ezin da erabili SIMa."</string> diff --git a/packages/SystemUI/res-keyguard/values-fa/strings.xml b/packages/SystemUI/res-keyguard/values-fa/strings.xml index f274f5fd7a57..4822487b2029 100644 --- a/packages/SystemUI/res-keyguard/values-fa/strings.xml +++ b/packages/SystemUI/res-keyguard/values-fa/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • درحال شارژ شدن"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • درحال شارژ سریع"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • آهستهآهسته شارژ میشود"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • برای محافظت از باتری، شارژ بهینه میشود"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • در شارژ وسیله جانبی مشکلی وجود دارد"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"شبکه قفل شد"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"سیمکارتی وجود ندارد"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"سیمکارت قابلاستفاده نیست."</string> diff --git a/packages/SystemUI/res-keyguard/values-fi/strings.xml b/packages/SystemUI/res-keyguard/values-fi/strings.xml index dd9ce2e4453f..39b0529e7a26 100644 --- a/packages/SystemUI/res-keyguard/values-fi/strings.xml +++ b/packages/SystemUI/res-keyguard/values-fi/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ladataan"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ladataan nopeasti"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ladataan hitaasti"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lataus optimoitu akun suojaamiseksi"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ongelma laturin kanssa"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Verkko lukittu"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Ei SIM-korttia"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"SIM-korttia ei voi käyttää."</string> diff --git a/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml b/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml index 742f56e7f214..fcf505282dd5 100644 --- a/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml +++ b/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"En recharge : <xliff:g id="PERCENTAGE">%s</xliff:g>"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"En recharge rapide : <xliff:g id="PERCENTAGE">%s</xliff:g>"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"En recharge lente : <xliff:g id="PERCENTAGE">%s</xliff:g>"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Recharge optimisée pour protéger la pile"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Problème concernant l\'accessoire de recharge"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Réseau verrouillé"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Aucune carte SIM"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"La carte SIM est inutilisable."</string> diff --git a/packages/SystemUI/res-keyguard/values-fr/strings.xml b/packages/SystemUI/res-keyguard/values-fr/strings.xml index 92d24c4bbc28..ffa0b1d5f26d 100644 --- a/packages/SystemUI/res-keyguard/values-fr/strings.xml +++ b/packages/SystemUI/res-keyguard/values-fr/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Recharge…"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Recharge rapide…"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Recharge lente"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Recharge optimisée pour protéger la batterie"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Problème de recharge de l\'accessoire"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Réseau verrouillé"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Aucune SIM"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"SIM inutilisable."</string> diff --git a/packages/SystemUI/res-keyguard/values-gl/strings.xml b/packages/SystemUI/res-keyguard/values-gl/strings.xml index 4837de2139ac..1163ed00e783 100644 --- a/packages/SystemUI/res-keyguard/values-gl/strings.xml +++ b/packages/SystemUI/res-keyguard/values-gl/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando rapidamente"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando lentamente"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carga optimizada para protexer a batería"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Problema co accesorio de carga"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Bloqueada pola rede"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Non hai ningunha SIM"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"A SIM non se pode usar."</string> diff --git a/packages/SystemUI/res-keyguard/values-gu/strings.xml b/packages/SystemUI/res-keyguard/values-gu/strings.xml index 7f8c6d824f93..bfbb2f280256 100644 --- a/packages/SystemUI/res-keyguard/values-gu/strings.xml +++ b/packages/SystemUI/res-keyguard/values-gu/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ચાર્જિંગ"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ઝડપથી ચાર્જિંગ"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ધીમેથી ચાર્જિંગ"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • બૅટરીની સુરક્ષા કરવા માટે, ચાર્જિંગ ઑપ્ટિમાઇઝ કરવામાં આવ્યું છે"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ચાર્જિંગ ઍક્સેસરીમાં સમસ્યા"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"નેટવર્ક લૉક થયું"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"કોઈ સિમ કાર્ડ નથી"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"ઉપયોગમાં ન લઈ શકાતું સિમ કાર્ડ."</string> diff --git a/packages/SystemUI/res-keyguard/values-hi/strings.xml b/packages/SystemUI/res-keyguard/values-hi/strings.xml index 01b99ec5700e..9ee840de657f 100644 --- a/packages/SystemUI/res-keyguard/values-hi/strings.xml +++ b/packages/SystemUI/res-keyguard/values-hi/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • चार्ज हो रहा है"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • तेज़ चार्ज हो रहा है"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • धीरे चार्ज हो रहा है"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • बैटरी को नुकसान से बचाने के लिए, चार्जिंग को ऑप्टिमाइज़ किया गया"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • चार्जर ऐक्सेसरी से जुड़ी समस्या"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"नेटवर्क लॉक किया हुआ है"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"कोई सिम नहीं है"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"सिम को हमेशा के लिए बंद कर दिया गया है."</string> diff --git a/packages/SystemUI/res-keyguard/values-hr/strings.xml b/packages/SystemUI/res-keyguard/values-hr/strings.xml index 0206faf7f2ad..4edd7d2fae2d 100644 --- a/packages/SystemUI/res-keyguard/values-hr/strings.xml +++ b/packages/SystemUI/res-keyguard/values-hr/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • punjenje"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • brzo punjenje"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • sporo punjenje"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Punjenje se optimizira radi zaštite baterije"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Problem s priborom za punjenje"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Mreža je zaključana"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Nema SIM-a"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"SIM je neupotrebljiv."</string> diff --git a/packages/SystemUI/res-keyguard/values-hu/strings.xml b/packages/SystemUI/res-keyguard/values-hu/strings.xml index 8575e10884ce..f27156d4ea3f 100644 --- a/packages/SystemUI/res-keyguard/values-hu/strings.xml +++ b/packages/SystemUI/res-keyguard/values-hu/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Töltés"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Gyors töltés"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lassú töltés"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimalizált töltés az akkumulátor védelme érdekében"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Probléma van a töltőtartozékkal"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Hálózat zárolva"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Nincs SIM"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"Nem használható SIM."</string> diff --git a/packages/SystemUI/res-keyguard/values-hy/strings.xml b/packages/SystemUI/res-keyguard/values-hy/strings.xml index a7c3abab1d84..a402721ee4fc 100644 --- a/packages/SystemUI/res-keyguard/values-hy/strings.xml +++ b/packages/SystemUI/res-keyguard/values-hy/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Լիցքավորում"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Արագ լիցքավորում"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Դանդաղ լիցքավորում"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Մարտկոցը պաշտպանելու համար լիցքավորումն օպտիմալացվել է"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Լիցքավորիչի հետ կապված խնդիր"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Ցանցը կողպված է"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"SIM քարտ չկա"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"Անվավեր SIM քարտ։"</string> diff --git a/packages/SystemUI/res-keyguard/values-in/strings.xml b/packages/SystemUI/res-keyguard/values-in/strings.xml index f9a840fc5aa8..229419efa250 100644 --- a/packages/SystemUI/res-keyguard/values-in/strings.xml +++ b/packages/SystemUI/res-keyguard/values-in/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengisi daya"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengisi daya dengan cepat"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengisi daya dengan lambat"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Pengisian daya dioptimalkan untuk melindungi baterai"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Masalah dengan aksesori pengisian daya"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Jaringan terkunci"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Tidak ada SIM"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"SIM tidak dapat digunakan."</string> diff --git a/packages/SystemUI/res-keyguard/values-is/strings.xml b/packages/SystemUI/res-keyguard/values-is/strings.xml index b7147c201919..7edcdbd109b9 100644 --- a/packages/SystemUI/res-keyguard/values-is/strings.xml +++ b/packages/SystemUI/res-keyguard/values-is/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Í hleðslu"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Hröð hleðsla"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Hæg hleðsla"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Hleðsla fínstillt til að vernda rafhlöðuna"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Vandamál með hleðslubúnað"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Net læst"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Ekkert SIM-kort"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"Ónothæft SIM-kort."</string> diff --git a/packages/SystemUI/res-keyguard/values-it/strings.xml b/packages/SystemUI/res-keyguard/values-it/strings.xml index 9e1b18740750..7856a492936e 100644 --- a/packages/SystemUI/res-keyguard/values-it/strings.xml +++ b/packages/SystemUI/res-keyguard/values-it/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • In carica"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ricarica veloce"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ricarica lenta"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ricarica ottimizzata per proteggere la batteria"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Problema relativo all\'accessorio di ricarica"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Rete bloccata"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Nessuna SIM presente"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"SIM inutilizzabile."</string> diff --git a/packages/SystemUI/res-keyguard/values-iw/strings.xml b/packages/SystemUI/res-keyguard/values-iw/strings.xml index 16316cebcc7c..9182c5aaf9d5 100644 --- a/packages/SystemUI/res-keyguard/values-iw/strings.xml +++ b/packages/SystemUI/res-keyguard/values-iw/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • בטעינה"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • בטעינה מהירה"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • בטעינה איטית"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • הטעינה עברה אופטימיזציה כדי להגן על הסוללה"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • יש בעיה עם אביזר הטעינה"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"הרשת נעולה"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"אין כרטיס SIM"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"לא ניתן להשתמש בכרטיס ה-SIM הזה."</string> diff --git a/packages/SystemUI/res-keyguard/values-ja/strings.xml b/packages/SystemUI/res-keyguard/values-ja/strings.xml index 6e8f42369e0a..e589f85cc91e 100644 --- a/packages/SystemUI/res-keyguard/values-ja/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ja/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 充電中"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 急速充電中"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 低速充電中"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • バッテリーを保護するために、充電が最適化されています"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 充電用アクセサリに関する問題"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"ネットワークがロックされました"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"SIM がありません"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"SIM が使用できません。"</string> diff --git a/packages/SystemUI/res-keyguard/values-ka/strings.xml b/packages/SystemUI/res-keyguard/values-ka/strings.xml index a31243d9f5f9..0fe5a397466f 100644 --- a/packages/SystemUI/res-keyguard/values-ka/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ka/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • იტენება"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • სწრაფად იტენება"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ნელა იტენება"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • დატენვა ოპტიმიზირებულია ბატარეის დასაცავად"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • დამტენი დამხმარე მოწყობილობის პრობლემა"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"ქსელი ჩაკეტილია"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"SIM არ არის"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"გამოუყენებელი SIM."</string> diff --git a/packages/SystemUI/res-keyguard/values-kk/strings.xml b/packages/SystemUI/res-keyguard/values-kk/strings.xml index 6a777832d07d..3882c5d1ecac 100644 --- a/packages/SystemUI/res-keyguard/values-kk/strings.xml +++ b/packages/SystemUI/res-keyguard/values-kk/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарядталуда"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Жылдам зарядтау"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Баяу зарядталуда"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Батареяны қорғау үшін зарядтау оңтайландырылды"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарядтау құрылғысына қатысты мәселе туындады."</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Желі құлыптаулы"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"SIM картасы жоқ."</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"SIM картасын пайдалану мүмкін емес."</string> diff --git a/packages/SystemUI/res-keyguard/values-km/strings.xml b/packages/SystemUI/res-keyguard/values-km/strings.xml index cda9520862aa..0ebda041daec 100644 --- a/packages/SystemUI/res-keyguard/values-km/strings.xml +++ b/packages/SystemUI/res-keyguard/values-km/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • កំពុងសាកថ្ម"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • កំពុងសាកថ្មយ៉ាងឆាប់រហ័ស"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • កំពុងសាកថ្មយឺត"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • បានបង្កើនប្រសិទ្ធភាពនៃការសាក ដើម្បីការពារថ្ម"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • បញ្ហាពាក់ព័ន្ធនឹងគ្រឿងសាកថ្ម"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"បណ្ដាញជាប់សោ"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"គ្មានស៊ីមទេ"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"ស៊ីមមិនអាចប្រើបាន។"</string> diff --git a/packages/SystemUI/res-keyguard/values-kn/strings.xml b/packages/SystemUI/res-keyguard/values-kn/strings.xml index e24005a08fc9..4dbefed138b9 100644 --- a/packages/SystemUI/res-keyguard/values-kn/strings.xml +++ b/packages/SystemUI/res-keyguard/values-kn/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ಚಾರ್ಜ್ ಮಾಡಲಾಗುತ್ತಿದೆ"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ವೇಗವಾಗಿ ಚಾರ್ಜ್ಮಾಡಲಾಗುತ್ತಿದೆ"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ನಿಧಾನವಾಗಿ ಚಾರ್ಜ್ ಮಾಡಲಾಗುತ್ತಿದೆ"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ಬ್ಯಾಟರಿಯನ್ನು ರಕ್ಷಿಸಲು ಚಾರ್ಜಿಂಗ್ ಅನ್ನು ಆಪ್ಟಿಮೈಸ್ ಮಾಡಲಾಗಿದೆ"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ಚಾರ್ಜಿಂಗ್ ಪರಿಕರ ಕುರಿತು ಸಮಸ್ಯೆ ಇದೆ"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"ನೆಟ್ವರ್ಕ್ ಲಾಕ್ ಆಗಿದೆ"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"SIM ಇಲ್ಲ"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"SIM ನಿಷ್ಪ್ರಯೋಜಕವಾಗಿದೆ."</string> diff --git a/packages/SystemUI/res-keyguard/values-ko/strings.xml b/packages/SystemUI/res-keyguard/values-ko/strings.xml index 7378cc78e5e6..e0d764502a0c 100644 --- a/packages/SystemUI/res-keyguard/values-ko/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ko/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 충전 중"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 고속 충전 중"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 저속 충전 중"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 배터리 보호를 위해 충전 최적화됨"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 충전 액세서리 문제"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"네트워크 잠김"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"SIM 없음"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"SIM을 사용할 수 없습니다."</string> diff --git a/packages/SystemUI/res-keyguard/values-ky/strings.xml b/packages/SystemUI/res-keyguard/values-ky/strings.xml index 88f0b97b385b..cc777a29ae0d 100644 --- a/packages/SystemUI/res-keyguard/values-ky/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ky/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Кубатталууда"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Тез кубатталууда"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Жай кубатталууда"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Батареяны коргоо үчүн кубаттоо процесси оптималдаштырылды"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Кубаттоочу шайманда көйгөй бар"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Тармак кулпуланган"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"SIM карта жок"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"Жараксыз SIM карта."</string> diff --git a/packages/SystemUI/res-keyguard/values-lo/strings.xml b/packages/SystemUI/res-keyguard/values-lo/strings.xml index 00a382a7cd02..ce2fa3bfe3f2 100644 --- a/packages/SystemUI/res-keyguard/values-lo/strings.xml +++ b/packages/SystemUI/res-keyguard/values-lo/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ກຳລັງສາກ"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ກຳລັງສາກແບບດ່ວນ"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ກຳລັງສາກແບບຊ້າ"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ການສາກຖືກປັບໃຫ້ເໝາະສົມເພື່ອປົກປ້ອງແບັດເຕີຣີ"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ບັນຫາກັບອຸປະກອນເສີມໃນການສາກ"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"ເຄືອຂ່າຍຖືກລັອກ"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"ບໍ່ມີຊິມ"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"ຊິມໃຊ້ບໍ່ໄດ້."</string> diff --git a/packages/SystemUI/res-keyguard/values-lt/strings.xml b/packages/SystemUI/res-keyguard/values-lt/strings.xml index 31c410790556..4344b61c2375 100644 --- a/packages/SystemUI/res-keyguard/values-lt/strings.xml +++ b/packages/SystemUI/res-keyguard/values-lt/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Įkraunama"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Greitai įkraunama"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lėtai įkraunama"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Įkrovimas optimizuotas siekiant apsaugoti akumuliatorių"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Su įkrovimo priedu susijusi problema"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Tinklas užrakintas"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Nėra SIM kortelės"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"Nenaudojama SIM kortelė."</string> diff --git a/packages/SystemUI/res-keyguard/values-lv/strings.xml b/packages/SystemUI/res-keyguard/values-lv/strings.xml index ecf223351942..b5215119e968 100644 --- a/packages/SystemUI/res-keyguard/values-lv/strings.xml +++ b/packages/SystemUI/res-keyguard/values-lv/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Notiek uzlāde"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Notiek ātrā uzlāde"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Notiek lēnā uzlāde"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Uzlāde optimizēta, lai saudzētu akumulatoru"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Problēma ar uzlādes ierīci"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Tīkls ir bloķēts."</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Nav SIM kartes"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"SIM karte nav izmantojama."</string> diff --git a/packages/SystemUI/res-keyguard/values-mk/strings.xml b/packages/SystemUI/res-keyguard/values-mk/strings.xml index 3f089b991b92..7fe966fc76fe 100644 --- a/packages/SystemUI/res-keyguard/values-mk/strings.xml +++ b/packages/SystemUI/res-keyguard/values-mk/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Се полни"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Брзо полнење"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Бавно полнење"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Полнењето е оптимизирано за да се заштити батеријата"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Проблем со додатокот за полнење"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Мрежата е заклучена"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Нема SIM-картичка"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"SIM-картичката е неупотреблива."</string> diff --git a/packages/SystemUI/res-keyguard/values-ml/strings.xml b/packages/SystemUI/res-keyguard/values-ml/strings.xml index be1ea89688ff..afd7c40ada0a 100644 --- a/packages/SystemUI/res-keyguard/values-ml/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ml/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ചാർജ് ചെയ്യുന്നു"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • വേഗത്തിൽ ചാർജ് ചെയ്യുന്നു"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • പതുക്കെ ചാർജ് ചെയ്യുന്നു"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ബാറ്ററി പരിരക്ഷിക്കാൻ ചാർജിംഗ് ഒപ്റ്റിമൈസ് ചെയ്തു"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ചാർജിംഗ് ആക്സസറിയുമായി ബന്ധപ്പെട്ട പ്രശ്നം"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"നെറ്റ്വർക്ക് ലോക്കുചെയ്തു"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"സിം ഇല്ല"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"ഉപയോഗശൂന്യമായ സിം."</string> diff --git a/packages/SystemUI/res-keyguard/values-mn/strings.xml b/packages/SystemUI/res-keyguard/values-mn/strings.xml index 54fdecd761ac..d29daa560475 100644 --- a/packages/SystemUI/res-keyguard/values-mn/strings.xml +++ b/packages/SystemUI/res-keyguard/values-mn/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Цэнэглэж байна"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Хурдан цэнэглэж байна"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Удаан цэнэглэж байна"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Батарейг хамгаалахын тулд цэнэглэх явцыг оновчилсон"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Цэнэглэх хэрэгсэлд асуудал гарлаа"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Сүлжээ түгжигдсэн"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"SIM байхгүй"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"Ашиглах боломжгүй SIM."</string> diff --git a/packages/SystemUI/res-keyguard/values-mr/strings.xml b/packages/SystemUI/res-keyguard/values-mr/strings.xml index eff4c7a9b2d3..85522d7dafc4 100644 --- a/packages/SystemUI/res-keyguard/values-mr/strings.xml +++ b/packages/SystemUI/res-keyguard/values-mr/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • चार्ज होत आहे"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • वेगाने चार्ज होत आहे"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • सावकाश चार्ज होत आहे"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • बॅटरीचे संरक्षण करण्यासाठी चार्जिंग ऑप्टिमाइझ केले आहे"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • चार्जिंगच्या ॲक्सेसरीसंबंधित समस्या"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"नेटवर्क लॉक केले"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"सिम नाही"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"वापरण्यायोग्य नसलेले सिम."</string> diff --git a/packages/SystemUI/res-keyguard/values-ms/strings.xml b/packages/SystemUI/res-keyguard/values-ms/strings.xml index d9eb4ca07c6d..1b8ef075737e 100644 --- a/packages/SystemUI/res-keyguard/values-ms/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ms/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengecas"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengecas dengan cepat"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengecas dengan perlahan"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Pengecasan dioptimumkan untuk melindungi bateri"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Isu berkaitan aksesori pengecasan"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Rangkaian dikunci"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Tiada SIM"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"SIM tidak boleh digunakan."</string> diff --git a/packages/SystemUI/res-keyguard/values-my/strings.xml b/packages/SystemUI/res-keyguard/values-my/strings.xml index afbce26a945f..a638d17dde3e 100644 --- a/packages/SystemUI/res-keyguard/values-my/strings.xml +++ b/packages/SystemUI/res-keyguard/values-my/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • အားသွင်းနေသည်"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • အမြန်အားသွင်းနေသည်"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • နှေးကွေးစွာ အားသွင်းနေသည်"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ဘက်ထရီကာကွယ်ရန် အားသွင်းခြင်းကို အကောင်းဆုံးပြင်ဆင်ထားသည်"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • အားသွင်းပစ္စည်းတွင် ပြဿနာရှိသည်"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"ကွန်ရက်ကို လော့ခ်ချထားသည်"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"ဆင်းမ်ကတ် မရှိပါ"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"ဆင်းမ်ကတ်ကို သုံး၍မရပါ။"</string> diff --git a/packages/SystemUI/res-keyguard/values-nb/strings.xml b/packages/SystemUI/res-keyguard/values-nb/strings.xml index 3098e878f5b6..b289b72cf16a 100644 --- a/packages/SystemUI/res-keyguard/values-nb/strings.xml +++ b/packages/SystemUI/res-keyguard/values-nb/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lader"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lader raskt"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lader sakte"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ladingen er optimalisert for å beskytte batteriet"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Problem med ladetilbehøret"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Nettverket er låst"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Ingen SIM-kort"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"SIM-kortet kan ikke brukes."</string> diff --git a/packages/SystemUI/res-keyguard/values-ne/strings.xml b/packages/SystemUI/res-keyguard/values-ne/strings.xml index 45b88197a52d..fc6f21fe11f6 100644 --- a/packages/SystemUI/res-keyguard/values-ne/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ne/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • चार्ज गरिँदै"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • द्रुत गतिमा चार्ज गरिँदै छ"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • मन्द गतिमा चार्ज गरिँदै"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ब्याट्री जोगाउन चार्ज गर्ने प्रक्रिया अप्टिमाइज गरिएको छ"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • चार्ज गर्ने एक्सेसरीमा कुनै समस्या आयो"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"नेटवर्क लक भएको छ"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"SIM कार्ड हालिएको छैन"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"यो SIM कार्ड प्रयोग गर्न मिल्दैन।"</string> diff --git a/packages/SystemUI/res-keyguard/values-nl/strings.xml b/packages/SystemUI/res-keyguard/values-nl/strings.xml index af24d4002e0e..093c7b7f51e8 100644 --- a/packages/SystemUI/res-keyguard/values-nl/strings.xml +++ b/packages/SystemUI/res-keyguard/values-nl/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Opladen"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Snel opladen"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Langzaam opladen"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Opladen geoptimaliseerd om de batterij te beschermen"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Probleem met oplaadaccessoire"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Netwerk vergrendeld"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Geen simkaart"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"Onbruikbare simkaart."</string> diff --git a/packages/SystemUI/res-keyguard/values-or/strings.xml b/packages/SystemUI/res-keyguard/values-or/strings.xml index 8cae9874bbf3..76dbdaf33357 100644 --- a/packages/SystemUI/res-keyguard/values-or/strings.xml +++ b/packages/SystemUI/res-keyguard/values-or/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ଚାର୍ଜ ହେଉଛି"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ଦ୍ରୁତ ଭାବେ ଚାର୍ଜ ହେଉଛି"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ଧୀରେ ଚାର୍ଜ ହେଉଛି"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ବେଟେରୀକୁ ସୁରକ୍ଷିତ ରଖିବା ପାଇଁ ଚାର୍ଜିଂକୁ ଅପ୍ଟିମାଇଜ କରାଯାଇଛି"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ଚାର୍ଜିଂ ଆକସେସୋରୀ ସହ ସମସ୍ୟା"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"ନେଟୱର୍କକୁ ଲକ୍ କରାଯାଇଛି"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"କୌଣସି SIM ନାହିଁ"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"ବ୍ୟବହାର ଅଯୋଗ୍ୟ ଥିବା SIM।"</string> diff --git a/packages/SystemUI/res-keyguard/values-pa/strings.xml b/packages/SystemUI/res-keyguard/values-pa/strings.xml index 18959c8fb9e8..10e9eeff055f 100644 --- a/packages/SystemUI/res-keyguard/values-pa/strings.xml +++ b/packages/SystemUI/res-keyguard/values-pa/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ਤੇਜ਼ੀ ਨਾਲ ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ਹੌਲੀ-ਹੌਲੀ ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ਬੈਟਰੀ ਦੀ ਸੁਰੱਖਿਆ ਲਈ ਚਾਰਜਿੰਗ ਨੂੰ ਸੁਯੋਗ ਬਣਾਇਆ ਗਿਆ"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ਚਾਰਜ ਕਰਨ ਵਾਲੀ ਐਕਸੈਸਰੀ ਸੰਬੰਧੀ ਸਮੱਸਿਆ"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"ਨੈੱਟਵਰਕ ਲਾਕ ਕੀਤਾ ਗਿਆ"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"ਕੋਈ ਸਿਮ ਨਹੀਂ ਹੈ"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"ਬੇਕਾਰ ਸਿਮ।"</string> diff --git a/packages/SystemUI/res-keyguard/values-pl/strings.xml b/packages/SystemUI/res-keyguard/values-pl/strings.xml index bd00ba9bb5f6..08cbc29d3995 100644 --- a/packages/SystemUI/res-keyguard/values-pl/strings.xml +++ b/packages/SystemUI/res-keyguard/values-pl/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ładowanie"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Szybkie ładowanie"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Wolne ładowanie"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ładowanie zoptymalizowane w celu ochrony baterii"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Problem z akcesoriami do ładowania"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Sieć zablokowana"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Brak karty SIM"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"Nie można użyć karty SIM."</string> diff --git a/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml b/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml index 54e270f8eb2c..efd1c75d6cce 100644 --- a/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml +++ b/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando rapidamente"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando lentamente"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregamento otimizado para proteger a bateria"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Problema com o acessório de carregamento"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Rede bloqueada"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Sem chip"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"Chip inutilizável."</string> diff --git a/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml b/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml index 2e37bde883de..38cc437e332c 100644 --- a/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml +++ b/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • A carregar…"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • A carregar rapidamente…"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • A carregar lentamente…"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregamento otimizado para proteger a bateria"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Problema com o acessório de carregamento"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Rede bloqueada"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Sem SIM"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"SIM inutilizável."</string> diff --git a/packages/SystemUI/res-keyguard/values-pt/strings.xml b/packages/SystemUI/res-keyguard/values-pt/strings.xml index 54e270f8eb2c..efd1c75d6cce 100644 --- a/packages/SystemUI/res-keyguard/values-pt/strings.xml +++ b/packages/SystemUI/res-keyguard/values-pt/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando rapidamente"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando lentamente"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregamento otimizado para proteger a bateria"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Problema com o acessório de carregamento"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Rede bloqueada"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Sem chip"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"Chip inutilizável."</string> diff --git a/packages/SystemUI/res-keyguard/values-ro/strings.xml b/packages/SystemUI/res-keyguard/values-ro/strings.xml index ead092099326..e3cfd3ee9ac9 100644 --- a/packages/SystemUI/res-keyguard/values-ro/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ro/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Se încarcă"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Se încarcă rapid"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Se încarcă lent"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Încărcarea este optimizată pentru a proteja bateria"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Problemă legată de accesoriul de încărcare"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Rețea blocată"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Niciun card SIM"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"Cardul SIM nu se poate folosi."</string> diff --git a/packages/SystemUI/res-keyguard/values-ru/strings.xml b/packages/SystemUI/res-keyguard/values-ru/strings.xml index 595fba5dfcb2..b5b326632dc7 100644 --- a/packages/SystemUI/res-keyguard/values-ru/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ru/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"Идет зарядка (<xliff:g id="PERCENTAGE">%s</xliff:g>)"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"Идет быстрая зарядка (<xliff:g id="PERCENTAGE">%s</xliff:g>)"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"Идет медленная зарядка (<xliff:g id="PERCENTAGE">%s</xliff:g>)"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарядка оптимизирована для защиты батареи"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Проблема с зарядным устройством"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Сеть заблокирована"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"SIM-карта отсутствует"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"SIM-карту невозможно использовать."</string> diff --git a/packages/SystemUI/res-keyguard/values-si/strings.xml b/packages/SystemUI/res-keyguard/values-si/strings.xml index b6a742234fe0..ecd3f3f9afa2 100644 --- a/packages/SystemUI/res-keyguard/values-si/strings.xml +++ b/packages/SystemUI/res-keyguard/values-si/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ආරෝපණය වෙමින්"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • වේගයෙන් ආරෝපණය වෙමින්"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • සෙමින් ආරෝපණය වෙමින්"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • බැටරිය ආරක්ෂා කිරීම සඳහා ආරෝපණය ප්රශස්ත කර ඇත"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ආරෝපණ උපාංගයේ ගැටලුව"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"ජාලය අගුළු දමා ඇත"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"SIM නැත"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"භාවිත කළ නොහැකි SIM."</string> diff --git a/packages/SystemUI/res-keyguard/values-sk/strings.xml b/packages/SystemUI/res-keyguard/values-sk/strings.xml index 5e34a94ffccd..c38ba64789e3 100644 --- a/packages/SystemUI/res-keyguard/values-sk/strings.xml +++ b/packages/SystemUI/res-keyguard/values-sk/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nabíja sa"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nabíja sa rýchlo"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nabíja sa pomaly"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nabíjanie je optimalizované, aby sa chránila batéria"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Problém s nabíjacím príslušenstvom"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Sieť je zablokovaná"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Žiadna SIM karta"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"Nepoužiteľná SIM karta."</string> diff --git a/packages/SystemUI/res-keyguard/values-sl/strings.xml b/packages/SystemUI/res-keyguard/values-sl/strings.xml index 3508f3b3af6e..c066f50b0132 100644 --- a/packages/SystemUI/res-keyguard/values-sl/strings.xml +++ b/packages/SystemUI/res-keyguard/values-sl/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • polnjenje"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • hitro polnjenje"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • počasno polnjenje"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Polnjenje je optimizirano zaradi zaščite baterije"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • težava s pripomočkom za polnjenje"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Omrežje je zaklenjeno"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Ni kartice SIM."</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"Kartica SIM je neuporabna."</string> diff --git a/packages/SystemUI/res-keyguard/values-sq/strings.xml b/packages/SystemUI/res-keyguard/values-sq/strings.xml index 8d71b0f941b7..1dc93fd1b824 100644 --- a/packages/SystemUI/res-keyguard/values-sq/strings.xml +++ b/packages/SystemUI/res-keyguard/values-sq/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Po karikohet"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Po karikohet me shpejtësi"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Po karikohet ngadalë"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Karikimi u optimizua për të mbrojtur baterinë"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Problem me aksesorin e karikimit"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Rrjeti është i kyçur"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Nuk ka kartë SIM"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"Kartë SIM e papërdorshme."</string> diff --git a/packages/SystemUI/res-keyguard/values-sr/strings.xml b/packages/SystemUI/res-keyguard/values-sr/strings.xml index 409395285343..34cb06b07b31 100644 --- a/packages/SystemUI/res-keyguard/values-sr/strings.xml +++ b/packages/SystemUI/res-keyguard/values-sr/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Пуни се"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Брзо се пуни"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Споро се пуни"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Пуњење је оптимизовано да би се заштитила батерија"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Проблем са додатним прибором за пуњење"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Мрежа је закључана"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Нема SIM-а"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"Неупотребљив SIM."</string> diff --git a/packages/SystemUI/res-keyguard/values-sv/strings.xml b/packages/SystemUI/res-keyguard/values-sv/strings.xml index 5b01f39a6a11..76c5dca8490d 100644 --- a/packages/SystemUI/res-keyguard/values-sv/strings.xml +++ b/packages/SystemUI/res-keyguard/values-sv/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laddas"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laddas snabbt"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laddas långsamt"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laddningen har optimerats för att skydda batteriet"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ett problem uppstod med att ladda tillbehöret"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Nätverk låst"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Inget SIM-kort"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"SIM-kortet går inte att använda."</string> diff --git a/packages/SystemUI/res-keyguard/values-sw/strings.xml b/packages/SystemUI/res-keyguard/values-sw/strings.xml index 9bc6c225aedd..b310ab9ee47a 100644 --- a/packages/SystemUI/res-keyguard/values-sw/strings.xml +++ b/packages/SystemUI/res-keyguard/values-sw/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Inachaji"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Inachaji kwa kasi"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Inachaji pole pole"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Hali ya kuchaji imeboreshwa ili kulinda betri"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Kifuasi cha kuchaji kina hitilafu"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Mtandao umefungwa"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Hakuna SIM"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"SIM haiwezi kutumika."</string> diff --git a/packages/SystemUI/res-keyguard/values-ta/strings.xml b/packages/SystemUI/res-keyguard/values-ta/strings.xml index 20eb8ef3e43e..f31137aade62 100644 --- a/packages/SystemUI/res-keyguard/values-ta/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ta/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • சார்ஜாகிறது"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • வேகமாகச் சார்ஜாகிறது"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • மெதுவாகச் சார்ஜாகிறது"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • பேட்டரியைப் பாதுகாக்க சார்ஜிங் மேம்படுத்தப்பட்டுள்ளது"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • சார்ஜரில் சிக்கல் உள்ளது"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"நெட்வொர்க் பூட்டப்பட்டது"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"சிம் இல்லை"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"பயன்படுத்த முடியாத சிம்."</string> diff --git a/packages/SystemUI/res-keyguard/values-te/strings.xml b/packages/SystemUI/res-keyguard/values-te/strings.xml index d496944798f9..924678f6f32e 100644 --- a/packages/SystemUI/res-keyguard/values-te/strings.xml +++ b/packages/SystemUI/res-keyguard/values-te/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ఛార్జ్ అవుతోంది"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • వేగంగా ఛార్జ్ అవుతోంది"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • నెమ్మదిగా ఛార్జ్ అవుతోంది"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • బ్యాటరీని రక్షించడానికి ఛార్జింగ్ ఆప్టిమైజ్ చేయబడింది"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ఛార్జింగ్ యాక్సెసరీతో సమస్య ఉంది"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"నెట్వర్క్ లాక్ చేయబడింది"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"SIM లేదు"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"వినియోగించలేని SIM."</string> diff --git a/packages/SystemUI/res-keyguard/values-th/strings.xml b/packages/SystemUI/res-keyguard/values-th/strings.xml index 605d0772ac6e..980ed9994d73 100644 --- a/packages/SystemUI/res-keyguard/values-th/strings.xml +++ b/packages/SystemUI/res-keyguard/values-th/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • กำลังชาร์จ"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • กำลังชาร์จอย่างเร็ว"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • กำลังชาร์จอย่างช้าๆ"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ปรับการชาร์จให้เหมาะสมเพื่อถนอมแบตเตอรี่"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ปัญหาเกี่ยวกับอุปกรณ์เสริมสำหรับการชาร์จ"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"เครือข่ายถูกล็อก"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"ไม่มี SIM"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"SIM ใช้งานไม่ได้"</string> diff --git a/packages/SystemUI/res-keyguard/values-tl/strings.xml b/packages/SystemUI/res-keyguard/values-tl/strings.xml index 040ec9e9b703..b054b1ec2c02 100644 --- a/packages/SystemUI/res-keyguard/values-tl/strings.xml +++ b/packages/SystemUI/res-keyguard/values-tl/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nagcha-charge"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mabilis na nagcha-charge"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mabagal na nagcha-charge"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Naka-optimize ang pag-charge para protektahan ang baterya"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Isyu sa pag-charge ng accessory"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Naka-lock ang network"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Walang SIM"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"Hindi magagamit na SIM."</string> diff --git a/packages/SystemUI/res-keyguard/values-tr/strings.xml b/packages/SystemUI/res-keyguard/values-tr/strings.xml index 750ba1174fe8..343cea1851b7 100644 --- a/packages/SystemUI/res-keyguard/values-tr/strings.xml +++ b/packages/SystemUI/res-keyguard/values-tr/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Şarj oluyor"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Hızlı şarj oluyor"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Yavaş şarj oluyor"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Şarj işlemi pili korumak üzere optimize edildi"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Şarj aksesuarı ile ilgili sorun"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Ağ kilitli"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"SIM yok"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"Kullanılamayan SIM."</string> diff --git a/packages/SystemUI/res-keyguard/values-uk/strings.xml b/packages/SystemUI/res-keyguard/values-uk/strings.xml index 169ea1f16eec..56ca79d405dc 100644 --- a/packages/SystemUI/res-keyguard/values-uk/strings.xml +++ b/packages/SystemUI/res-keyguard/values-uk/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Заряджання"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Швидке заряджання"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Повільне заряджання"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Заряджання оптимізовано, щоб захистити акумулятор"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Проблема із зарядним пристроєм"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Мережу заблоковано"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Немає SIM-карти"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"Непридатна SIM-карта."</string> diff --git a/packages/SystemUI/res-keyguard/values-ur/strings.xml b/packages/SystemUI/res-keyguard/values-ur/strings.xml index d7f7b653e92e..3c47dd59b977 100644 --- a/packages/SystemUI/res-keyguard/values-ur/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ur/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • چارج ہو رہا ہے"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • تیزی سے چارج ہو رہا ہے"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • آہستہ چارج ہو رہا ہے"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • بیٹری کی حفاظت کے لیے چارجنگ کو بہتر بنایا گیا"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • چارجنگ ایکسیسری کے ساتھ مسئلہ"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"نیٹ ورک مقفل ہو گیا"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"کوئی SIM نہیں ہے"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"ناقابل استعمال SIM۔"</string> diff --git a/packages/SystemUI/res-keyguard/values-uz/strings.xml b/packages/SystemUI/res-keyguard/values-uz/strings.xml index 40dbaf3142fa..f58628b6b706 100644 --- a/packages/SystemUI/res-keyguard/values-uz/strings.xml +++ b/packages/SystemUI/res-keyguard/values-uz/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Quvvat olmoqda"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Tezkor quvvat olmoqda"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Sekin quvvat olmoqda"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Batareyani himoyalash uchun quvvatlash optimallashtirildi"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Quvvatlash aksessuari bilan muammo"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Tarmoq qulflangan"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"SIM kartasiz"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"Ishlamaydigan SIM."</string> diff --git a/packages/SystemUI/res-keyguard/values-vi/strings.xml b/packages/SystemUI/res-keyguard/values-vi/strings.xml index d5a33d37bc66..7fb272f0dc0e 100644 --- a/packages/SystemUI/res-keyguard/values-vi/strings.xml +++ b/packages/SystemUI/res-keyguard/values-vi/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Đang sạc"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Đang sạc nhanh"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Đang sạc chậm"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Quá trình sạc được tối ưu hoá để bảo vệ pin"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Có vấn đề với phụ kiện sạc"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Mạng đã bị khóa"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Không có SIM"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"SIM không sử dụng được."</string> diff --git a/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml index 6de9ff944882..79e00fda09d3 100644 --- a/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml +++ b/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在充电"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在快速充电"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在慢速充电"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 为保护电池,充电方式已优化"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 充电配件有问题"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"网络已锁定"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"没有 SIM 卡"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"SIM 卡无法使用。"</string> diff --git a/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml index 11966ca08dce..76f366a19d14 100644 --- a/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml +++ b/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在充電"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 快速充電中"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 慢速充電中"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 為保護電池,系統已優化充電"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 充電配件發生問題"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"網絡已鎖定"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"沒有 SIM 卡"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"SIM 卡無法使用。"</string> diff --git a/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml index e4f868a093d3..e7e25c1a4d42 100644 --- a/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml +++ b/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 充電中"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 快速充電中"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 慢速充電中"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 為保護電池,充電效能已最佳化"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 充電配件有問題"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"網路已鎖定"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"沒有 SIM 卡"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"SIM 卡無法使用。"</string> diff --git a/packages/SystemUI/res-keyguard/values-zu/strings.xml b/packages/SystemUI/res-keyguard/values-zu/strings.xml index 4fadc2e55ee9..61f956afceb3 100644 --- a/packages/SystemUI/res-keyguard/values-zu/strings.xml +++ b/packages/SystemUI/res-keyguard/values-zu/strings.xml @@ -33,8 +33,10 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Iyashaja"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ishaja kaningi"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ishaja kancane"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ukushaja kuthuthukisiwe ukuze kuvikelwe ibhethri"</string> - <string name="keyguard_plugged_in_incompatible_charger" msgid="3687961801947819076">"<xliff:g id="PERCENTAGE">%s</xliff:g> • • Inkinga ngesisekeli sokushaja"</string> + <!-- no translation found for keyguard_plugged_in_charging_limited (5369697538556777542) --> + <skip /> + <!-- no translation found for keyguard_plugged_in_incompatible_charger (6384203333154532125) --> + <skip /> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Inethiwekhi ivaliwe"</string> <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Ayikho i-SIM"</string> <string name="keyguard_permanent_disabled_sim_message_short" msgid="3955052454216046100">"I-SIM engasebenziseki."</string> diff --git a/packages/SystemUI/res/drawable/ic_satellite_connected_0.xml b/packages/SystemUI/res/drawable/ic_satellite_connected_0.xml new file mode 100644 index 000000000000..045c19eb09dc --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_satellite_connected_0.xml @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2023 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + <path + android:pathData="M14.73,3.36L17.63,6.2C17.83,6.39 17.83,6.71 17.63,6.91L16.89,7.65C16.69,7.85 16.37,7.85 16.18,7.65L13.34,4.78C13.15,4.59 13.15,4.28 13.34,4.08L14.01,3.37C14.2,3.17 14.52,3.16 14.72,3.36H14.73ZM14.37,1C13.85,1 13.32,1.2 12.93,1.61L11.56,3.06C10.8,3.84 10.81,5.09 11.58,5.86L15.13,9.41C15.52,9.8 16.03,10 16.55,10C17.07,10 17.58,9.8 17.97,9.41L19.42,7.96C20.21,7.17 20.2,5.89 19.4,5.12L15.77,1.57C15.38,1.19 14.88,1 14.37,1Z" + android:fillColor="#fff"/> + <path + android:pathData="M4.73,13.36L7.63,16.2C7.83,16.39 7.83,16.71 7.63,16.91L6.89,17.65C6.69,17.85 6.37,17.85 6.18,17.65L3.34,14.78C3.15,14.59 3.15,14.28 3.34,14.08L4.01,13.37C4.2,13.17 4.52,13.16 4.72,13.36H4.73ZM4.37,11C3.85,11 3.32,11.2 2.93,11.61L1.56,13.06C0.8,13.84 0.81,15.09 1.58,15.86L5.13,19.41C5.52,19.8 6.03,20 6.55,20C7.07,20 7.58,19.8 7.97,19.41L9.42,17.96C10.21,17.17 10.2,15.89 9.4,15.12L5.77,11.57C5.38,11.19 4.88,11 4.37,11Z" + android:fillColor="#fff"/> + <path + android:pathData="M8.622,5.368L5.372,8.618L10.112,13.358C11.009,14.255 12.464,14.255 13.362,13.358C14.259,12.46 14.259,11.005 13.362,10.108L8.622,5.368Z" + android:fillColor="#fff"/> + <path + android:pathData="M16.766,3.169L13.471,6.464L14.532,7.525L17.827,4.23L16.766,3.169Z" + android:fillColor="#fff"/> + <path + android:pathData="M14.728,5.226L3.478,16.476L4.538,17.536L15.788,6.286L14.728,5.226Z" + android:fillColor="#fff"/> + <path + android:pathData="M12.63,9.38L9.38,12.63L4.67,7.92C3.77,7.02 3.77,5.57 4.67,4.67C5.57,3.77 7.02,3.77 7.92,4.67L12.63,9.38Z" + android:fillColor="#fff"/> + <path + android:pathData="M11,22.48V21.48C11,21.21 11.22,21 11.49,20.99C16.63,20.8 20.75,16.62 20.99,11.48C21,11.21 21.21,11 21.48,11H22.48C22.76,11 23,11.24 22.99,11.52C22.72,17.73 17.73,22.73 11.52,22.99C11.24,23 11,22.77 11,22.48Z" + android:fillAlpha="0.3" + android:fillColor="#fff"/> + <path + android:pathData="M11,18.98V17.98C11,17.71 11.21,17.51 11.48,17.49C14.69,17.26 17.33,14.7 17.49,11.49C17.5,11.22 17.71,11.01 17.98,11.01H18.79C19.26,11.01 19.5,11.25 19.48,11.53C19.22,15.8 15.79,19.23 11.52,19.49C11.24,19.51 11,19.27 11,18.99V18.98Z" + android:fillAlpha="0.3" + android:fillColor="#fff"/> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_satellite_connected_1.xml b/packages/SystemUI/res/drawable/ic_satellite_connected_1.xml new file mode 100644 index 000000000000..5e012ab7edbd --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_satellite_connected_1.xml @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2023 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + <path + android:pathData="M14.73,3.36L17.63,6.2C17.83,6.39 17.83,6.71 17.63,6.91L16.89,7.65C16.69,7.85 16.37,7.85 16.18,7.65L13.34,4.78C13.15,4.59 13.15,4.28 13.34,4.08L14.01,3.37C14.2,3.17 14.52,3.16 14.72,3.36H14.73ZM14.37,1C13.85,1 13.32,1.2 12.93,1.61L11.56,3.06C10.8,3.84 10.81,5.09 11.58,5.86L15.13,9.41C15.52,9.8 16.03,10 16.55,10C17.07,10 17.58,9.8 17.97,9.41L19.42,7.96C20.21,7.17 20.2,5.89 19.4,5.12L15.77,1.57C15.38,1.19 14.88,1 14.37,1Z" + android:fillColor="#fff"/> + <path + android:pathData="M4.73,13.36L7.63,16.2C7.83,16.39 7.83,16.71 7.63,16.91L6.89,17.65C6.69,17.85 6.37,17.85 6.18,17.65L3.34,14.78C3.15,14.59 3.15,14.28 3.34,14.08L4.01,13.37C4.2,13.17 4.52,13.16 4.72,13.36H4.73ZM4.37,11C3.85,11 3.32,11.2 2.93,11.61L1.56,13.06C0.8,13.84 0.81,15.09 1.58,15.86L5.13,19.41C5.52,19.8 6.03,20 6.55,20C7.07,20 7.58,19.8 7.97,19.41L9.42,17.96C10.21,17.17 10.2,15.89 9.4,15.12L5.77,11.57C5.38,11.19 4.88,11 4.37,11Z" + android:fillColor="#fff"/> + <path + android:pathData="M8.622,5.368L5.372,8.618L10.112,13.358C11.009,14.255 12.464,14.255 13.362,13.358C14.259,12.46 14.259,11.005 13.362,10.108L8.622,5.368Z" + android:fillColor="#fff"/> + <path + android:pathData="M16.766,3.169L13.471,6.464L14.532,7.525L17.827,4.23L16.766,3.169Z" + android:fillColor="#fff"/> + <path + android:pathData="M14.728,5.226L3.478,16.476L4.538,17.536L15.788,6.286L14.728,5.226Z" + android:fillColor="#fff"/> + <path + android:pathData="M12.63,9.38L9.38,12.63L4.67,7.92C3.77,7.02 3.77,5.57 4.67,4.67C5.57,3.77 7.02,3.77 7.92,4.67L12.63,9.38Z" + android:fillColor="#fff"/> + <path + android:pathData="M11,22.48V21.48C11,21.21 11.22,21 11.49,20.99C16.63,20.8 20.75,16.62 20.99,11.48C21,11.21 21.21,11 21.48,11H22.48C22.76,11 23,11.24 22.99,11.52C22.72,17.73 17.73,22.73 11.52,22.99C11.24,23 11,22.77 11,22.48Z" + android:fillAlpha="0.3" + android:fillColor="#fff"/> + <path + android:pathData="M11,18.98V17.98C11,17.71 11.21,17.51 11.48,17.49C14.69,17.26 17.33,14.7 17.49,11.49C17.5,11.22 17.71,11.01 17.98,11.01H18.79C19.26,11.01 19.5,11.25 19.48,11.53C19.22,15.8 15.79,19.23 11.52,19.49C11.24,19.51 11,19.27 11,18.99V18.98Z" + android:fillColor="#fff"/> +</vector> + diff --git a/packages/SystemUI/res/drawable/ic_satellite_connected_2.xml b/packages/SystemUI/res/drawable/ic_satellite_connected_2.xml new file mode 100644 index 000000000000..d8a9a703260d --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_satellite_connected_2.xml @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2023 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + <path + android:pathData="M14.73,3.36L17.63,6.2C17.83,6.39 17.83,6.71 17.63,6.91L16.89,7.65C16.69,7.85 16.37,7.85 16.18,7.65L13.34,4.78C13.15,4.59 13.15,4.28 13.34,4.08L14.01,3.37C14.2,3.17 14.52,3.16 14.72,3.36H14.73ZM14.37,1C13.85,1 13.32,1.2 12.93,1.61L11.56,3.06C10.8,3.84 10.81,5.09 11.58,5.86L15.13,9.41C15.52,9.8 16.03,10 16.55,10C17.07,10 17.58,9.8 17.97,9.41L19.42,7.96C20.21,7.17 20.2,5.89 19.4,5.12L15.77,1.57C15.38,1.19 14.88,1 14.37,1Z" + android:fillColor="#fff"/> + <path + android:pathData="M4.73,13.36L7.63,16.2C7.83,16.39 7.83,16.71 7.63,16.91L6.89,17.65C6.69,17.85 6.37,17.85 6.18,17.65L3.34,14.78C3.15,14.59 3.15,14.28 3.34,14.08L4.01,13.37C4.2,13.17 4.52,13.16 4.72,13.36H4.73ZM4.37,11C3.85,11 3.32,11.2 2.93,11.61L1.56,13.06C0.8,13.84 0.81,15.09 1.58,15.86L5.13,19.41C5.52,19.8 6.03,20 6.55,20C7.07,20 7.58,19.8 7.97,19.41L9.42,17.96C10.21,17.17 10.2,15.89 9.4,15.12L5.77,11.57C5.38,11.19 4.88,11 4.37,11Z" + android:fillColor="#fff"/> + <path + android:pathData="M8.622,5.368L5.372,8.618L10.112,13.358C11.009,14.255 12.464,14.255 13.362,13.358C14.259,12.46 14.259,11.005 13.362,10.108L8.622,5.368Z" + android:fillColor="#fff"/> + <path + android:pathData="M16.766,3.169L13.471,6.464L14.532,7.525L17.827,4.23L16.766,3.169Z" + android:fillColor="#fff"/> + <path + android:pathData="M14.728,5.226L3.478,16.476L4.538,17.536L15.788,6.286L14.728,5.226Z" + android:fillColor="#fff"/> + <path + android:pathData="M12.63,9.38L9.38,12.63L4.67,7.92C3.77,7.02 3.77,5.57 4.67,4.67C5.57,3.77 7.02,3.77 7.92,4.67L12.63,9.38Z" + android:fillColor="#fff"/> + <path + android:pathData="M11,22.48V21.48C11,21.21 11.22,21 11.49,20.99C16.63,20.8 20.75,16.62 20.99,11.48C21,11.21 21.21,11 21.48,11H22.48C22.76,11 23,11.24 22.99,11.52C22.72,17.73 17.73,22.73 11.52,22.99C11.24,23 11,22.77 11,22.48Z" + android:fillColor="#fff"/> + <path + android:pathData="M11,18.98V17.98C11,17.71 11.21,17.51 11.48,17.49C14.69,17.26 17.33,14.7 17.49,11.49C17.5,11.22 17.71,11.01 17.98,11.01H18.79C19.26,11.01 19.5,11.25 19.48,11.53C19.22,15.8 15.79,19.23 11.52,19.49C11.24,19.51 11,19.27 11,18.99V18.98Z" + android:fillColor="#fff"/> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_satellite_not_connected.xml b/packages/SystemUI/res/drawable/ic_satellite_not_connected.xml new file mode 100644 index 000000000000..dec9930959a0 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_satellite_not_connected.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2023 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0" + > + <path + android:pathData="M14.73,3.36L17.63,6.2C17.83,6.39 17.83,6.71 17.63,6.91L16.89,7.65C16.69,7.85 16.37,7.85 16.18,7.65L13.34,4.78C13.15,4.59 13.15,4.28 13.34,4.08L14.01,3.37C14.2,3.17 14.52,3.16 14.72,3.36H14.73ZM14.37,1C13.85,1 13.32,1.2 12.93,1.61L11.56,3.06C10.8,3.84 10.81,5.09 11.58,5.86L15.13,9.41C15.52,9.8 16.03,10 16.55,10C17.07,10 17.58,9.8 17.97,9.41L19.42,7.96C20.21,7.17 20.2,5.89 19.4,5.12L15.77,1.57C15.38,1.19 14.88,1 14.37,1Z" + android:fillColor="#fff"/> + <path + android:pathData="M4.73,13.36L7.63,16.2C7.83,16.39 7.83,16.71 7.63,16.91L6.89,17.65C6.69,17.85 6.37,17.85 6.18,17.65L3.34,14.78C3.15,14.59 3.15,14.28 3.34,14.08L4.01,13.37C4.2,13.17 4.52,13.16 4.72,13.36H4.73ZM4.37,11C3.85,11 3.32,11.2 2.93,11.61L1.56,13.06C0.8,13.84 0.81,15.09 1.58,15.86L5.13,19.41C5.52,19.8 6.03,20 6.55,20C7.07,20 7.58,19.8 7.97,19.41L9.42,17.96C10.21,17.17 10.2,15.89 9.4,15.12L5.77,11.57C5.38,11.19 4.88,11 4.37,11Z" + android:fillColor="#fff"/> + <path + android:pathData="M8.622,5.368L5.372,8.618L10.112,13.358C11.009,14.255 12.464,14.255 13.362,13.358C14.259,12.46 14.259,11.005 13.362,10.108L8.622,5.368Z" + android:fillColor="#fff"/> + <path + android:pathData="M16.766,3.169L13.471,6.464L14.532,7.525L17.827,4.23L16.766,3.169Z" + android:fillColor="#fff"/> + <path + android:pathData="M14.728,5.226L3.478,16.476L4.538,17.536L15.788,6.286L14.728,5.226Z" + android:fillColor="#fff"/> + <path + android:pathData="M12.63,9.38L9.38,12.63L4.67,7.92C3.77,7.02 3.77,5.57 4.67,4.67C5.57,3.77 7.02,3.77 7.92,4.67L12.63,9.38Z" + android:fillColor="#fff"/> +</vector> diff --git a/packages/SystemUI/res/layout/bindable_status_bar_icon.xml b/packages/SystemUI/res/layout/bindable_status_bar_icon.xml new file mode 100644 index 000000000000..ee4d05c3bda5 --- /dev/null +++ b/packages/SystemUI/res/layout/bindable_status_bar_icon.xml @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="utf-8"?><!-- + ~ Copyright (C) 2023 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<!-- Base layout that provides a single bindable icon_view id image view --> +<com.android.systemui.statusbar.pipeline.shared.ui.view.SingleBindableStatusBarIconView + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:gravity="center_vertical" + > + + <ImageView + android:id="@+id/icon_view" + android:layout_height="@dimen/status_bar_bindable_icon_size" + android:layout_width="wrap_content" + android:layout_gravity="center_vertical" + android:padding="@dimen/status_bar_bindable_icon_padding" + android:scaleType="fitCenter" + /> + +</com.android.systemui.statusbar.pipeline.shared.ui.view.SingleBindableStatusBarIconView> diff --git a/packages/SystemUI/res/layout/qs_customize_panel_content.xml b/packages/SystemUI/res/layout/qs_customize_panel_content.xml index 3be99939ba0f..156c98333f3a 100644 --- a/packages/SystemUI/res/layout/qs_customize_panel_content.xml +++ b/packages/SystemUI/res/layout/qs_customize_panel_content.xml @@ -37,6 +37,7 @@ android:layout_height="wrap_content" android:background="@drawable/qs_customizer_toolbar" android:navigationContentDescription="@*android:string/action_bar_up_description" + android:titleTextAppearance="@*android:style/TextAppearance.DeviceDefault.Widget.ActionBar.Title" style="@style/QSCustomizeToolbar" /> diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml index aeb831114f07..30ac963d9291 100644 --- a/packages/SystemUI/res/values-af/strings.xml +++ b/packages/SystemUI/res/values-af/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Kon nie Gesigslot opstel nie. Gaan na Instellings toe om weer te probeer."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Raak die vingerafdruksensor"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Druk die ontsluitikoon om voort te gaan"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"Gesig word nie herken nie. Gebruik eerder vingerafdruk."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"Gesig word nie herken nie"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Gebruik eerder vingerafdruk"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"Gesigslot is onbeskikbaar"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth gekoppel."</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laai tans • Vol oor <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Swiep links om die gemeenskaplike tutoriaal te begin"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Maak die legstukredigeerder oop"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Pasmaak"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Maak toe"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Voeg by, verwyder en herrangskik jou legstukke in hierdie spasie"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Voeg meer legstukke by"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Langdruk om legstukke te pasmaak"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"Verwyder"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Voeg legstuk by"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Klaar"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"Skakel Bluetooth aan?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"Jy moet Bluetooth aanskakel om jou sleutelbord aan jou tablet te koppel."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Skakel aan"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Kragkennisgewingkontroles"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Aan – gesiggegrond"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"Met kragkennisgewingkontroles kan jy \'n belangrikheidvlak van 0 tot 5 vir \'n program se kennisgewings stel. \n\n"<b>"Vlak 5"</b>" \n- Wys aan die bokant van die kennisgewinglys \n- Laat volskermonderbreking toe \n- Wys altyd opspringkennisgewings \n\n"<b>"Vlak 4"</b>" \n- Verhoed volskermonderbreking \n- Wys altyd opspringkennisgewings \n\n"<b>"Vlak 3"</b>" \n- Verhoed volskermonderbreking \n- Verhoed opspringkennisgewings \n\n"<b>"Vlak 2"</b>" \n- Verhoed volskermonderbreking \n- Verhoed opspringkennisgewings \n- Moet nooit \'n klank maak of vibreer nie \n\n"<b>"Vlak 1"</b>" \n- Verhoed volskermonderbreking \n- Verhoed opspringkennisgewings \n- Moet nooit \'n klank maak of vibreer nie \n- Versteek van sluitskerm en statusbalk \n- Wys aan die onderkant van die kennisgewinglys \n\n"<b>"Vlak 0"</b>" \n- Blokkeer alle kennisgewings van die program af"</string> <string name="inline_done_button" msgid="6043094985588909584">"Klaar"</string> <string name="inline_ok_button" msgid="603075490581280343">"Pas toe"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Skakel kennisgewings af"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"Opstelling"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"Berging"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"Wenke"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"Toeganklikheid"</string> <string name="instant_apps" msgid="8337185853050247304">"Kitsprogramme"</string> <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> loop tans"</string> <string name="instant_apps_message" msgid="6112428971833011754">"Program is oopgemaak sonder dat dit geïnstalleer is."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Tik om toeganklikheidkenmerke oop te maak Pasmaak of vervang knoppie in Instellings.\n\n"<annotation id="link">"Bekyk instellings"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Skuif knoppie na kant om dit tydelik te versteek"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Ontdoen"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"Toeganklikheidknoppie is versteek"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Tik om toeganklikheidknoppie te wys"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g>-kortpad is verwyder"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# kortpad is verwyder}other{# kortpaaie is verwyder}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Beweeg na links bo"</string> diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml index 8bad367f11b0..9aa6a1826515 100644 --- a/packages/SystemUI/res/values-am/strings.xml +++ b/packages/SystemUI/res/values-am/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"በመልክ መክፈትን ማዋቀር አልተቻለም። እንደገና ለመሞከር ወደ ቅንብሮች ይሂዱ።"</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"የጣት አሻራ ዳሳሹን ይንኩ"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"ለመቀጠል የክፈት አዶውን ይጫኑ"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"ፊቱ አልታወቀም። በምትኩ የጣት አሻራ ይጠቀሙ።"</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"ፊቱ አልታወቀም።"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"በምትኩ የጣት አሻራን ይጠቀሙ"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"በመልክ መክፈት አይገኝም"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"ብሉቱዝ ተያይዟል።"</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ኃይል በመሙላት ላይ • በ<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ውስጥ ይሞላል"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"የጋራ አጋዥ ሥልጠናውን ለመጀመር ወደ ግራ ያንሸራትቱ።"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"የምግብር አርታዒውን ይክፈቱ"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"አብጅ"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"አሰናብት"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"በዚህ ቦታ ላይ የእርስዎን ምግብሮች ያክሉ፣ ያስወግዱ እና እንደገና ቅደም ተከተል ያስይዙ"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"ተጨማሪ ምግብሮችን ያክሉ"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"ምግብሮችን ለማበጀት በረጅሙ ይጫኑ"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"አስወግድ"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"ምግብር አክል"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"ተከናውኗል"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"ብሉቱዝ ይብራ?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"የቁልፍ ሰሌዳዎን ከእርስዎ ጡባዊ ጋር ለማገናኘት በመጀመሪያ ብሉቱዝን ማብራት አለብዎት።"</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"አብራ"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"የኃይል ማሳወቂያ መቆጣጠሪያዎች"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"በርቷል - መልክ ላይ የተመሠረተ"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"በኃይል ማሳወቂያ መቆጣጠሪያዎች አማካኝነት የአንድ መተግበሪያ ማሳወቂያዎች የአስፈላጊነት ደረጃ ከ0 እስከ 5 ድረስ ማዘጋጀት ይችላሉ። \n\n"<b>"ደረጃ 5"</b>" \n- በማሳወቂያ ዝርዝሩ አናት ላይ አሳይ \n- የሙሉ ማያ ገፅ ማቋረጥን ፍቀድ \n- ሁልጊዜ አጮልቀው ይመልከቱ \n\n"<b>"ደረጃ 4"</b>" \n- የሙሉ ማያ ገፅ ማቋረጥን ከልክል \n- ሁልጊዜ አጮልቀው ይመልከቱ \n\n"<b>"ደረጃ 3"</b>" \n- የሙሉ ማያ ገፅ ማቋረጥን ከልክል \n- በፍጹም አጮልቀው አይምልከቱ \n\n"<b>"ደረጃ 2"</b>" \n- የሙሉ ማያ ገፅ ማቋረጥን ይከልክሉ \n- በፍጹም አጮልቀው አይመልከቱ \n- ድምፅ እና ንዝረትን በፍጹም አይኑር \n\n"<b>"ደረጃ 1"</b>" \n- የሙሉ ማያ ገፅ ማቋረጥን ይከልክሉ \n- በፍጹም አጮልቀው አይመልከቱ \n- ድምፅ ወይም ንዝረትን በፍጹም አያደርጉ \n- ከመቆለፊያ ገፅ እና የሁኔታ አሞሌ ይደብቁ \n- በማሳወቂያ ዝርዝር ግርጌ ላይ አሳይ \n\n"<b>"ደረጃ 0"</b>" \n- ሁሉንም የመተግበሪያው ማሳወቂያዎች ያግዱ"</string> <string name="inline_done_button" msgid="6043094985588909584">"ተከናውኗል"</string> <string name="inline_ok_button" msgid="603075490581280343">"ተግብር"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"ማሳወቂያዎችን አጥፋ"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"ውቅረት"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"ማከማቻ"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"ፍንጮች"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"ተደራሽነት"</string> <string name="instant_apps" msgid="8337185853050247304">"የቅጽበት መተግበሪያዎች"</string> <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> አሂድ"</string> <string name="instant_apps_message" msgid="6112428971833011754">"መተግበሪያ ሳይጫን ተከፍቷል።"</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"የተደራሽነት ባህሪያትን ለመክፈት መታ ያድርጉ። ይህንን አዝራር በቅንብሮች ውስጥ ያብጁ ወይም ይተኩ።\n\n"<annotation id="link">"ቅንብሮችን አሳይ"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"ለጊዜው ለመደበቅ አዝራሩን ወደ ጠርዝ ያንቀሳቅሱ"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"ቀልብስ"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"የተደራሽነት አዝራር ተደብቋል"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"የተደራሽነት አዝራርን ለማሳየት መታ ያድርጉ"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> አቋራጭ ተወግዷል"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# አቋራጭ ተወግዷል}one{# አቋራጭ ተወግዷል}other{# አቋራጮች ተወግደዋል}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"ወደ ላይኛው ግራ አንቀሳቅስ"</string> diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml index 2566df7430d1..0874ffb2f4da 100644 --- a/packages/SystemUI/res/values-ar/strings.xml +++ b/packages/SystemUI/res/values-ar/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"تعذّر إعداد ميزة \"فتح الجهاز بالتعرّف على الوجه\". انتقِل إلى \"الإعدادات\" لإعادة المحاولة."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"المس أداة استشعار بصمة الإصبع"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"للمتابعة، اضغط على رمز فتح القفل."</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"يتعذّر التعرّف على الوجه. يمكنك استخدام بصمة إصبعك."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"يتعذّر التعرّف على الوجه."</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"يمكنك استخدام بصمة إصبعك."</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"ميزة \"فتح الجهاز بالتعرف على الوجه\" غير متاحة."</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"تم توصيل البلوتوث."</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • جارٍ الشحن • ستمتلئ البطارية خلال <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"مرِّر سريعًا لليمين لبدء الدليل التوجيهي العام."</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"فتح محرِّر التطبيقات المصغّرة"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"تخصيص"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"إغلاق"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"يمكنك في هذه المساحة إضافة التطبيقات المصغّرة وإزالتها وإعادة ترتيبها."</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"إضافة المزيد من التطبيقات المصغّرة"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"اضغط مع الاستمرار لتخصيص التطبيقات المصغّرة."</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"إزالة"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"إضافة تطبيق مصغّر"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"تم"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"تفعيل البلوتوث؟"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"لتوصيل لوحة المفاتيح بالجهاز اللوحي، يلزمك تفعيل بلوتوث أولاً."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"تفعيل"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"عناصر التحكم في إشعارات التشغيل"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"تفعيل - استنادًا للوجه"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"باستخدام عناصر التحكم في إشعار التشغيل، يمكنك ضبط مستوى الأهمية من 0 إلى 5 لإشعارات التطبيق. \n\n"<b>"المستوى 5"</b>" \n- العرض أعلى قائمة الإشعارات \n- يسمح بمقاطعة ملء الشاشة \n- الظهور الخاطف دائمًا \n\n"<b>"المستوى 4"</b>" \n- منع مقاطعة ملء الشاشة \n- الظهور الخاطف دائمًا \n\n"<b>"المستوى 3"</b>" \n- منع مقاطعة ملء الشاشة \n- عدم الظهور الخاطف أبدًا \n\n"<b>"المستوى 2"</b>" \n- منع مقاطعة ملء الشاشة \n- عدم الظهور الخاطف أبدًا \n- عدم إصدار أصوات واهتزاز \n\n"<b>"المستوى 1"</b>" \n- منع مقاطعة ملء الشاشة \n- عدم الظهور الخاطف أبدًا \n- عدم إصدار أصوات أو اهتزاز أبدًا \n- الإخفاء من شاشة القفل وشريط الحالة \n- العرض أسفل قائمة الإشعارات \n\n"<b>"المستوى 0"</b>" \n- حظر جميع الإشعارات من التطبيق"</string> <string name="inline_done_button" msgid="6043094985588909584">"تمّ"</string> <string name="inline_ok_button" msgid="603075490581280343">"تطبيق"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"إيقاف الإشعارات"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"عملية الإعداد"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"مساحة التخزين"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"تلميحات"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"أدوات تسهيل الاستخدام"</string> <string name="instant_apps" msgid="8337185853050247304">"التطبيقات الفورية"</string> <string name="instant_apps_title" msgid="8942706782103036910">"التطبيق <xliff:g id="APP">%1$s</xliff:g> قيد التشغيل"</string> <string name="instant_apps_message" msgid="6112428971833011754">"تمّ فتح التطبيق بدون تثبيته."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"انقر لفتح ميزات تسهيل الاستخدام. يمكنك تخصيص هذا الزر أو استبداله من الإعدادات.\n\n"<annotation id="link">"عرض الإعدادات"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"يمكنك نقل الزر إلى الحافة لإخفائه مؤقتًا."</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"تراجع"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"زر أدوات تسهيل الاستخدام مخفي"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"انقر لإظهار زر أدوات تسهيل الاستخدام."</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"تمت إزالة اختصار <xliff:g id="FEATURE_NAME">%s</xliff:g>."</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{تمت إزالة اختصار واحد.}zero{تمت إزالة # اختصار.}two{تمت إزالة اختصارَين.}few{تمت إزالة # اختصارات.}many{تمت إزالة # اختصارًا.}other{تمت إزالة # اختصار.}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"النقل إلى أعلى يمين الشاشة"</string> diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml index 591c125cc90d..03381880a6b7 100644 --- a/packages/SystemUI/res/values-as/strings.xml +++ b/packages/SystemUI/res/values-as/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"ফে’চ আনলক ছেট আপ কৰিব পৰা নগ’ল। পুনৰ চেষ্টা কৰিবলৈ ছেটিঙলৈ যাওক।"</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"ফিংগাৰপ্ৰিণ্ট ছেন্সৰটো স্পৰ্শ কৰক"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"অব্যাহত ৰাখিবলৈ আনলক কৰক চিহ্নটোত টিপক"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"মুখাৱয়ব চিনাক্ত কৰিব পৰা নাই। ইয়াৰ পৰিৱৰ্তে ফিংগাৰপ্ৰিণ্ট ব্যৱহাৰ কৰক।"</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"মুখাৱয়ব চিনাক্ত কৰিব পৰা নাই"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"ইয়াৰ সলনি ফিংগাৰপ্ৰিণ্ট ব্যৱহাৰ কৰক"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"ফেচ আনলক সুবিধা উপলব্ধ নহয়"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"ব্লুটুথ সংযোগ হ’ল।"</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • চাৰ্জ হৈ আছে • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>ত সম্পূৰ্ণ হ’ব"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"সম্প্ৰদায় সম্পৰ্কীয় নিৰ্দেশনা আৰম্ভ কৰিবলৈ বাওঁফালে ছোৱাইপ কৰক"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"ৱিজেট সম্পাদকটো খোলক"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"কাষ্টমাইজ কৰক"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"অগ্ৰাহ্য কৰক"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"এই স্পেচটোত আপোনাৰ ৱিজেটসমূহ যোগ দিয়ক, আঁতৰাওক আৰু সেইসমূহৰ ক্ৰম সলনি কৰক"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"অধিক ৱিজেট যোগ দিয়ক"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"ৱিজেট কাষ্টমাইজ কৰিবলৈ দীঘলীয়াকৈ টিপক"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"আঁতৰাওক"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"ৱিজেট যোগ দিয়ক"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"কৰা হ’ল"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"ব্লুটুথ অন কৰিবনে?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"আপোনাৰ টেবলেটত আপোনাৰ কীব\'ৰ্ড সংযোগ কৰিবলৈ আপুনি প্ৰথমে ব্লুটুথ অন কৰিব লাগিব।"</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"অন কৰক"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"জাননী নিয়ন্ত্ৰণৰ অধিক কৰ্তৃত্ব"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"অন আছে - মুখাৱয়ব ভিত্তিক"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"জাননী নিয়ন্ত্ৰণৰ অধিক কৰ্তৃত্বৰ সৈতে আপুনি এটা এপৰ জাননীৰ গুৰুত্বৰ স্তৰ ০ৰ পৰা ৫লৈ ছেট কৰিব পাৰে।\n\n"<b>"স্তৰ ৫"</b>" \n- জাননী তালিকাৰ একেবাৰে ওপৰত দেখুৱাওক \n- সম্পূৰ্ণ স্ক্ৰীনত থাকোঁতে ব্যাঘাত জন্মাবলৈ অনুমতি দিয়ক\n- সদায় ভুমুকি মাৰিবলৈ দিয়ক\n\n"<b>"স্তৰ ৪"</b>" \n- সম্পূৰ্ণ স্ক্ৰীনত থাকোঁতে ব্যাঘাত জন্মাবলৈ নিদিব\n- সদায় ভুমুকি মাৰিবলৈ দিয়ক\n\n"<b>"স্তৰ ৩"</b>" \n- সম্পূৰ্ণ স্ক্ৰীনত থাকোঁতে ব্যাঘাত জন্মাবলৈ নিদিব\n- কেতিয়াও ভুমুকি মাৰিবলৈ নিদিব\n\n"<b>"স্তৰ ২"</b>" \n- সম্পূর্ণ স্ক্ৰীনত থাকোঁতে ব্যাঘাত জন্মাবলৈ নিদিব \n- কেতিয়াও ভুমুকি মাৰিবলৈ নিদিব\n- কেতিয়াও শব্দ আৰু কম্পন কৰিবলৈ নিদিব\n\n"<b>" স্তৰ ১"</b>" \n- সম্পূৰ্ণ স্ক্ৰীনত থাকোঁতে ব্যাঘাত জন্মাবলৈ নিদিব\n- কেতিয়াও ভুমুকি মাৰিবলৈ নিদিব\n-কেতিয়াও শব্দ আৰু কম্পন কৰিবলৈ নিদিব \n- লক স্ক্ৰীন আৰু স্থিতি দণ্ডৰ পৰা লুকুৱাই ৰাখক \n- জাননী তালিকাৰ একেবাৰে তলত দেখুৱাওক\n\n"<b>"স্তৰ ০"</b>" \n- এই এপৰ আটাইবোৰ জাননী অৱৰোধ কৰক"</string> <string name="inline_done_button" msgid="6043094985588909584">"কৰা হ’ল"</string> <string name="inline_ok_button" msgid="603075490581280343">"প্ৰয়োগ কৰক"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"জাননী অফ কৰক"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"ছেটআপ"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"ষ্ট\'ৰেজ"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"ইংগিতবোৰ"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"সাধ্য সুবিধা"</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> চলি আছে"</string> <string name="instant_apps_message" msgid="6112428971833011754">"এপ্টো ইনষ্ট\'ল নকৰাকৈ খোলা হৈছে।"</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"সাধ্য সুবিধাসমূহ খুলিবলৈ টিপক। ছেটিঙত এই বুটামটো কাষ্টমাইজ অথবা সলনি কৰক।\n\n"<annotation id="link">"ছেটিং চাওক"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"বুটামটোক সাময়িকভাৱে লুকুৱাবলৈ ইয়াক একেবাৰে কাষলৈ লৈ যাওক"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"আনডু কৰক"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"সাধ্য-সুবিধা বুটাম লুকুৱাই ৰখা হৈছে"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"সাধ্য-সুবিধা বুটাম দেখুৱাবলৈ টিপক"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g>ৰ শ্বৰ্টকাট আঁতৰোৱা হ’ল"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# টা শ্বৰ্টকাট আঁতৰোৱা হ’ল}one{# টা শ্বৰ্টকাট আঁতৰোৱা হ’ল}other{# টা শ্বৰ্টকাট আঁতৰোৱা হ’ল}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"শীৰ্ষৰ বাওঁফালে নিয়ক"</string> diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml index 978c29500cff..c858c3b70ee1 100644 --- a/packages/SystemUI/res/values-az/strings.xml +++ b/packages/SystemUI/res/values-az/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Üz ilə Kiliddən Açma ayarlanmadı. Yenidən cəhd etmək üçün Ayarlara keçin."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Barmaq izi sensoruna klikləyin"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"\"Kiliddən çıxarın\" ikonasını basaraq davam edin"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"Üz tanınmadı. Barmaq izindən istifadə edin."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"Üz tanınmadı"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Barmaq izi istifadə edin"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"Üz ilə kiliddən çıxarma əlçatan deyil"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth qoşulub."</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Şarj edilir • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> sonra dolacaq"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"İcma təlimatını başlatmaq üçün sola sürüşdürün"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Vidcet redaktorunu açın"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Fərdiləşdirin"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Bağlayın"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Burada vidcetlər əlavə edin, silin və sırasını dəyişin"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Vidcetlər əlavə edin"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Basıb saxlayaraq vidcetləri fərdiləşdirin"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"Silin"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Vidcet əlavə edin"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Hazırdır"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"Bluetooth aktivləşsin?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"Tabletinizlə klaviaturaya bağlanmaq üçün ilk olaraq Bluetooth\'u aktivləşdirməlisiniz."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Aktivləşdirin"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Enerji bildiriş nəzarəti"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Aktiv - Üz əsaslı"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"Enerji bildiriş nəzarəti ilə, tətbiq bildirişləri üçün əhəmiyyət səviyyəsini 0-dan 5-ə kimi ayarlaya bilərsiniz. \n\n"<b>"Səviyyə 5"</b>" \n- Bildiriş siyahısının yuxarı hissəsində göstərin \n- Tam ekran kəsintisinə icazə verin \n- Hər zaman izləyin \n\n"<b>"Səviyyə 4"</b>" \n- Tam ekran kəsintisinin qarşısını alın \n- Hər zaman izləyin \n\n"<b>"Level 3"</b>" \n- Tam ekran kəsintisinin qarşısını alın \n- Heç vaxt izləməyin \n\n"<b>"Level 2"</b>" \n- Tam ekran kəsintisinin qarşısını alın \n- Heç vaxt izləməyin \n- Heç vaxt səsliyə və ya vibrasiyaya qoymayın \n\n"<b>"Səviyyə 1"</b>" \n- Prevent full screen interruption \n- Heç vaxt izləməyin \n- Heç vaxt səsliyə və ya vibrasiyaya qoymayın \n- Ekran kilidi və ya status panelindən gizlədin \n- Bildiriş siyahısının yuxarı hissəsində göstərin \n\n"<b>"Səviyyə 0"</b>" \n- Bütün bildirişləri tətbiqdən blok edin"</string> <string name="inline_done_button" msgid="6043094985588909584">"Hazırdır"</string> <string name="inline_ok_button" msgid="603075490581280343">"Tətbiq edin"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Bildirişləri deaktiv edin"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"Ayarlama"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"Yaddaş"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"Məsləhətlər"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"Əlçatımlıq"</string> <string name="instant_apps" msgid="8337185853050247304">"Ani Tətbiqlər"</string> <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> işləyir"</string> <string name="instant_apps_message" msgid="6112428971833011754">"Quraşdırılmadan açılan tətbiq."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Əlçatımlılıq funksiyalarını açmaq üçün toxunun. Ayarlarda bu düyməni fərdiləşdirin və ya dəyişdirin.\n\n"<annotation id="link">"Ayarlara baxın"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Düyməni müvəqqəti gizlətmək üçün kənara çəkin"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Geri qaytarın"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"Xüsusi imkanlar düyməsi gizlədildi"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Toxunaraq xüsusi imkanlar düyməsini göstərin"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> qısayol silindi"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# qısayol silindi}other{# qısayol silindi}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Yuxarıya sola köçürün"</string> diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml index 1668de0ee969..379c68eac184 100644 --- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml +++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Podešavanje otključavanja licem nije uspelo. Idite u Podešavanja da biste probali ponovo."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Dodirnite senzor za otisak prsta"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Pritisnite ikonu otključavanja za nastavak"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"Lice nije prepoznato. Koristite otisak prsta."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"Lice nije prepoznato"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Koristite otisak prsta"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"Otključavanje licem nije dostupno"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth je priključen."</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Puni se • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> do kraja punjenja"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Prevucite ulevo da biste započeli zajednički vodič"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Otvori uređivač vidžeta"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Prilagodite"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Odbaci"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Dodajte, uklonite i preuredite vidžete u ovom prostoru"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Dodajte još vidžeta"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Dugi pritisak za prilagođavanje vidžeta"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"Ukloni"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Dodaj vidžet"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Gotovo"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"Želite li da uključite Bluetooth?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"Da biste povezali tastaturu sa tabletom, prvo morate da uključite Bluetooth."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Uključi"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Napredne kontrole za obaveštenja"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Uključeno – na osnovu lica"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"Pomoću naprednih kontrola za obaveštenja možete da podesite nivo važnosti od 0. do 5. za obaveštenja aplikacije. \n\n"<b>"5. nivo"</b>" \n– Prikazuju se u vrhu liste obaveštenja \n- Dozvoli prekid režima celog ekrana \n– Uvek zaviruj \n\n"<b>"4. nivo"</b>" \n– Spreči prekid režima celog ekrana \n– Uvek zaviruj \n\n"<b>"3. nivo"</b>" \n– Spreči prekid režima celog ekrana \n– Nikada ne zaviruj \n\n"<b>"2. nivo"</b>" \n– Spreči prekid režima celog ekrana \n– Nikada ne zaviruj \n– Nikada ne proizvodi zvuk ili vibraciju \n\n"<b>"1. nivo"</b>" \n– Spreči prekid režima celog ekrana \n– Nikada ne zaviruj \n– Nikada ne proizvodi zvuk ili vibraciju \n– Sakrij na zaključanom ekranu i statusnoj traci \n– Prikazuju se u dnu liste obaveštenja \n\n"<b>"0. nivo"</b>" \n– Blokiraj sva obaveštenja iz aplikacije"</string> <string name="inline_done_button" msgid="6043094985588909584">"Gotovo"</string> <string name="inline_ok_button" msgid="603075490581280343">"Primeni"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Isključi obaveštenja"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"Podešavanje"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"Memorijski prostor"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"Saveti"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"Pristupačnost"</string> <string name="instant_apps" msgid="8337185853050247304">"Instant aplikacije"</string> <string name="instant_apps_title" msgid="8942706782103036910">"Aplikacija <xliff:g id="APP">%1$s</xliff:g> je pokrenuta"</string> <string name="instant_apps_message" msgid="6112428971833011754">"Aplikacija se otvorila bez instaliranja."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Dodirnite za funkcije pristupačnosti. Prilagodite ili zamenite ovo dugme u Podešavanjima.\n\n"<annotation id="link">"Podešavanja"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Pomerite dugme do ivice da biste ga privremeno sakrili"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Opozovi"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"Dugme Pristupačnost je skriveno"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Dodirnite za prikaz dugmeta Pristupačnost"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Prečica funkcije <xliff:g id="FEATURE_NAME">%s</xliff:g> je uklonjena"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# prečica je uklonjena}one{# prečica je uklonjena}few{# prečice su uklonjene}other{# prečica je uklonjeno}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Premesti gore levo"</string> diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml index 8d2addad30fa..97e8f17f9279 100644 --- a/packages/SystemUI/res/values-be/strings.xml +++ b/packages/SystemUI/res/values-be/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Не ўдалося наладзіць функцыю распазнавання твару. Каб паўтарыць, перайдзіце ў Налады."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Дакраніцеся да сканера адбіткаў пальцаў"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Каб працягнуць, націсніце на значок разблакіроўкі"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"Твар не распазнаны. Выкарыстайце адбітак пальца."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"Твар не распазнаны"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Скарыстайце адбітак пальца"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"Распазнаванне твару не працуе"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth-сувязь."</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ідзе зарадка • Поўны зарад праз <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Правядзіце пальцам па экране ўлева, каб азнаёміцца з дапаможнікам"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Адкрыць рэдактар віджэтаў"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Наладзіць"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Закрыць"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Дадаць ці выдаліць віджэты ў гэтай вобласці або змяніць іх парадак"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Дадаць іншыя віджэты"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Доўга націскайце, каб наладзіць віджэты"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"Выдаліць"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Дадаць віджэт"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Гатова"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"Уключыць Bluetooth?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"Для падлучэння клавіятуры да планшэта трэба спачатку ўключыць Bluetooth."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Уключыць"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Пашыранае кіраванне апавяшчэннямі"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Уключана – З улікам паставы галавы"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"З дапамогай пашыранага кіравання апавяшчэннямі вы можаце задаваць узровень важнасці апавяшчэнняў праграмы ад 0 да 5. \n\n"<b>"Узровень 5"</b>" \n- Паказваць уверсе спіса апавяшчэнняў \n- Дазваляць перапыняць рэжым поўнага экрана \n- Заўсёды дазваляць кароткі паказ \n\n"<b>"Узровень 4"</b>" \n- Забараняць перапыняць рэжым поўнага экрана \n- Заўсёды дазваляць кароткі паказ \n\n"<b>"Узровень 3"</b>" \n- Забараняць перапыняць рэжым поўнага экрана \n- Ніколі не дазваляць кароткі паказ \n\n"<b>"Узровень 2"</b>" \n- Забараняць перапыняць рэжым поўнага экрана \n- Ніколі не дазваляць кароткі паказ \n- Ніколі не прайграваць гук і не вібрыраваць \n\n"<b>"Узровень 1"</b>" \n- Забараняць перапыняць рэжым поўнага экрана \n- Ніколі не дазваляць кароткі паказ \n- Ніколі не прайграваць гук і не вібрыраваць \n- Хаваць з экрана блакіроўкі і панэлі стану \n- Паказваць унізе спіса апавяшчэнняў \n\n"<b>"Узровень 0"</b>" \n- Блакіраваць усе апавяшчэнні ад праграмы"</string> <string name="inline_done_button" msgid="6043094985588909584">"Гатова"</string> <string name="inline_ok_button" msgid="603075490581280343">"Прымяніць"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Выключыць апавяшчэнні"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"Наладжванне"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"Захоўванне"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"Падказкі"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"Спецыяльныя магчымасці"</string> <string name="instant_apps" msgid="8337185853050247304">"Імгненныя праграмы"</string> <string name="instant_apps_title" msgid="8942706782103036910">"Праграма \"<xliff:g id="APP">%1$s</xliff:g>\" запушчана"</string> <string name="instant_apps_message" msgid="6112428971833011754">"Праграма адкрыта без усталёўкі."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Націсніце, каб адкрыць спецыяльныя магчымасці. Рэгулюйце ці замяняйце кнопку ў Наладах.\n\n"<annotation id="link">"Прагляд налад"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Каб часова схаваць кнопку, перамясціце яе на край"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Адрабіць"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"Кнопка спецыяльных магчымасцей схавана"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Калі вы хочаце, каб яна з\'явілася, націсніце на апавяшчэнне"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Выдалены ярлык <xliff:g id="FEATURE_NAME">%s</xliff:g>"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{Выдалены # ярлык}one{Выдалены # ярлык}few{Выдалена # ярлыкі}many{Выдалена # ярлыкоў}other{Выдалена # ярлыка}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Перамясціць лявей і вышэй"</string> diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml index 6f5890fac679..f8585bca7616 100644 --- a/packages/SystemUI/res/values-bg/strings.xml +++ b/packages/SystemUI/res/values-bg/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Функцията „Отключване с лице“ не бе настроена. Отворете настройките, за да опитате отново."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Докоснете сензора за отпечатъци"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Натиснете иконата за отключване, за да продължите"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"Лицето не е разпознато. Използвайте отпечатък."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"Лицето не е разпознато"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Използвайте отпечатък"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"„Отключване с лице“ не е налице"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth е включен."</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Зарежда се • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до пълно зареждане"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Прекарайте пръст наляво, за да стартирате общия урок"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Отваряне на редактора на приспособлението"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Персонализиране"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Отхвърляне"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Добавяйте, премахвайте и пренареждайте приспособленията си в тази област"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Добавете още приспособления"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Натиснете продължително за персонализ. на приспос."</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"Премахване"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Добавяне на приспособление"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Готово"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"Да се включи ли Bluetooth?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"За да свържете клавиатурата с таблета си, първо трябва да включите Bluetooth."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Включване"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Контроли за известията"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Вкл. – въз основа на лицето"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"С помощта на контролите за известията можете да зададете ниво на важност от 0 до 5 за известията от дадено приложение. \n\n"<b>"Ниво 5"</b>" \n– Показване най-горе в списъка с известия. \n– Разрешаване на прекъсването на цял екран. \n– Известията винаги се показват мимолетно. \n\n"<b>"Ниво 4"</b>" \n– Предотвратяване на прекъсването на цял екран. \n– Известията винаги се показват мимолетно. \n\n"<b>"Ниво 3"</b>" \n– Предотвратяване на прекъсването на цял екран. \n– Известията никога не се показват мимолетно. \n\n"<b>"Ниво 2"</b>" \n– Предотвратяване на прекъсването на цял екран. \n– Известията никога не се показват мимолетно. \n– Без издаване на звуков сигнал и вибриране. \n\n"<b>"Ниво 1"</b>" \n– Предотвратяване на прекъсването на цял екран. \n– Известията никога не се показват мимолетно. \n– Без издаване на звуков сигнал и вибриране. \n– Скриване от заключения екран и лентата на състоянието. \n– Показване най-долу в списъка с известия. \n\n"<b>"Ниво 0"</b>" \n– Блокиране на всички известия от приложението."</string> <string name="inline_done_button" msgid="6043094985588909584">"Готово"</string> <string name="inline_ok_button" msgid="603075490581280343">"Прилагане"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Изключване на известията"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"Настройване"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"Хранилище"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"Съвети"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"Достъпност"</string> <string name="instant_apps" msgid="8337185853050247304">"Мигновени приложения"</string> <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> работи"</string> <string name="instant_apps_message" msgid="6112428971833011754">"Приложението се отвори, без да бъде инсталирано."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Докоснете, за да отворите функциите за достъпност. Персон./заменете бутона от настройките.\n\n"<annotation id="link">"Преглед на настройките"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Преместете бутона до края, за да го скриете временно"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Отмяна"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"Бутонът за достъпност е скрит"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Докоснете за показване на бутона за достъпност"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Прекият път за „<xliff:g id="FEATURE_NAME">%s</xliff:g>“ бе премахнат"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# пряк път бе премахнат}other{# преки пътя бяха премахнати}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Преместване горе вляво"</string> diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml index 601b29afa911..2229e8fc0817 100644 --- a/packages/SystemUI/res/values-bn/strings.xml +++ b/packages/SystemUI/res/values-bn/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"\'ফেস আনলক\' সেট-আপ করা যায়নি। আবার চেষ্টা করতে সেটিংসে যান।"</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"আঙ্গুলের ছাপের সেন্সর স্পর্শ করুন"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"চালিয়ে যেতে \'আনলক করুন\' আইকনে প্রেস করুন"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"মুখ চেনা যায়নি। পরিবর্তে ফিঙ্গারপ্রিন্ট ব্যবহার করুন।"</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"মুখ চেনা যায়নি"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"পরিবর্তে ফিঙ্গারপ্রিন্ট ব্যবহার করুন"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"\'ফেস আনলক\' উপলভ্য নেই"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"ব্লুটুথ সংযুক্ত হয়েছে৷"</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • চার্জ হচ্ছে • পুরো চার্জ হতে আরও <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> সময় লাগবে"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"কমিউনিটি টিউটোরিয়াল চালু করতে বাঁদিকে সোয়াইপ করুন"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"উইজেট এডিটর খুলুন"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"কাস্টমাইজ করুন"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"বাতিল করুন"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"এই স্পেসে আপনার উইজেট যোগ করুন, সরান ও আবার সাজান"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"আরও উইজেট যোগ করুন"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"উইজেট কাস্টমাইজ করতে বেশিক্ষণ প্রেস করুন"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"সরান"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"উইজেট যোগ করুন"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"হয়ে গেছে"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"ব্লুটুথ চালু করবেন?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"আপনার ট্যাবলেটের সাথে আপনার কীবোর্ড সংযুক্ত করতে, আপনাকে প্রথমে ব্লুটুথ চালু করতে হবে।"</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"চালু করুন"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"পাওয়ার বিজ্ঞপ্তির নিয়ন্ত্রণগুলি"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"চালু আছে - মুখের হিসেবে"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"পাওয়ার বিজ্ঞপ্তির নিয়ন্ত্রণগুলি ব্যহবার করে, আপনি কোনও অ্যাপ্লিকেশনের বিজ্ঞপ্তির জন্য ০ থেকে ৫ পর্যন্ত একটি গুরুত্বের লেভেলকে সেট করতে পারবেন৷ \n\n"<b>"লেভেল ৫"</b>" \n- বিজ্ঞপ্তি তালিকার শীর্ষে দেখায় \n- পূর্ণ স্ক্রিনের বাধাকে অনুমতি দেয় \n- সর্বদা স্ক্রিনে উপস্থিত হয় \n\n"<b>"লেভেল ৪"</b>" \n- পূর্ণ স্ক্রিনের বাধাকে আটকায় \n- সর্বদা স্ক্রিনে উপস্থিত হয় \n\n"<b>"লেভেল ৩"</b>" \n- পূর্ণ স্ক্রিনের বাধাকে আটকায় \n- কখনওই স্ক্রিনে উপস্থিত হয় না \n\n"<b>"লেভেল ২"</b>" \n- পূর্ণ স্ক্রিনের বাধাকে আটকায় \n- কখনওই স্ক্রিনে উপস্থিত হয় না \n- কখনওই শব্দ এবং কম্পন করে না \n\n"<b>"লেভেল ১"</b>" \n- পূর্ণ স্ক্রিনের বাধাকে আটকায় \n- কখনওই স্ক্রিনে উপস্থিত হয় না \n- কখনওই শব্দ এবং কম্পন করে না \n- লক স্ক্রিন এবং স্ট্যাটাস বার থেকে লুকায় \n- বিজ্ঞপ্তি তালিকার নীচের দিকে দেখায় \n\n"<b>"লেভেল ০"</b>" \n- অ্যাপ্লিকেশন থেকে সমস্ত বিজ্ঞপ্তিকে অবরূদ্ধ করে"</string> <string name="inline_done_button" msgid="6043094985588909584">"হয়ে গেছে"</string> <string name="inline_ok_button" msgid="603075490581280343">"প্রয়োগ করুন"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"বিজ্ঞপ্তি বন্ধ করুন"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"সেট-আপ"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"স্টোরেজ"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"হিন্ট"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"অ্যাক্সেসিবিলিটি"</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> চলছে"</string> <string name="instant_apps_message" msgid="6112428971833011754">"অ্যাপটি ইনস্টল না করে চালু করা হয়েছে।"</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"অ্যাক্সেসিবিলিটি ফিচার খুলতে ট্যাপ করুন। কাস্টমাইজ করুন বা সেটিংসে এই বোতামটি সরিয়ে দিন।\n\n"<annotation id="link">"সেটিংস দেখুন"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"এটি অস্থায়ীভাবে লুকাতে বোতামটি কোণে সরান"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"আগের অবস্থায় ফিরুন"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"অ্যাক্সেসিবিলিটি বোতাম লুকানো আছে"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"অ্যাক্সেসিবিলিটি বোতাম দেখাতে ট্যাপ করুন"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g>-এর শর্টকাট সরানো হয়েছে"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{#টি শর্টকাট সরানো হয়েছে}one{#টি শর্টকাট সরানো হয়েছে}other{#টি শর্টকাট সরানো হয়েছে}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"উপরে বাঁদিকে সরান"</string> diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml index 287eed74032c..d704b0ac5663 100644 --- a/packages/SystemUI/res/values-bs/strings.xml +++ b/packages/SystemUI/res/values-bs/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Postavljanje otključavanja licem nije uspjelo. Idite u Postavke da pokušate ponovo."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Dodirnite senzor za otisak prsta"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Nastavak pritiskanjem ikone za otključavanje"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"Lice nije prepoznato. Upotrijebite otisak prsta."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"Lice nije prepoznato"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Koristite otisak prsta"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"Otključavanje licem je nedostupno"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth je povezan."</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Punjenje • Potpuna napunjenost za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Prevucite ulijevo da pokrenete zajednički vodič"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Otvaranje uređivača vidžeta"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Prilagodite"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Odbaci"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Dodajte, uklonite i promijenite raspored vidžeta u ovom prostoru"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Dodajte još vidžeta"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Pritisnite i zadržite da prilagodite vidžete"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"Uklanjanje"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Dodajte vidžet"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Gotovo"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"Želiti li uključiti Bluetooth?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"Da povežete tastaturu sa tabletom, prvo morate uključiti Bluetooth."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Uključi"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Kontrole obavještenja o napajanju"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Uključeno – na osnovu lica"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"Uz kontrolu obavještenja o napajanju, možete postaviti nivo značaja obavještenja iz aplikacije, i to od nivoa 0 do 5. \n\n"<b>"Nivo 5"</b>" \n- Prikaži na vrhu liste obavještenja \n- Dopusti prekid prikaza cijelog ekrana \n- Uvijek izviruj \n\n"<b>"Nvio 4"</b>" \n- Spriječi prekid prikaza cijelog ekrana \n- Uvijek izviruj \n\n"<b>"Nivo 3"</b>" \n- Spriječi prekid prikaza cijelog ekrana \n- Nikad ne izviruj \n\n"<b>"Nivo 2"</b>" \n- Spriječi prekid prikaza cijelog ekrana \n- Nikad ne izviruj \n- Nikada ne puštaj zvuk ili vibraciju \n\n"<b>"Nivo 1"</b>" \n- Spriječi prekid prikaza cijelog ekrana \n- Nikada ne izviruj \n- Nikada ne puštaj zvuk ili vibraciju \n- Sakrij sa ekrana za zaključavanje i statusne trake \n- Prikaži na dnu liste obavještenja \n\n"<b>"Nivo 0"</b>" \n- Blokiraj sva obavještenja iz aplikacije"</string> <string name="inline_done_button" msgid="6043094985588909584">"Gotovo"</string> <string name="inline_ok_button" msgid="603075490581280343">"Primijeni"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Isključi obavještenja"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"Postavljanje"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"Pohrana"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"Savjeti"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"Pristupačnost"</string> <string name="instant_apps" msgid="8337185853050247304">"Instant aplikacije"</string> <string name="instant_apps_title" msgid="8942706782103036910">"Pokrenuta je aplikacija <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="instant_apps_message" msgid="6112428971833011754">"Aplikacija je otvorena bez prethodne instalacije."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Dodirnite da otvorite funkcije pristupačnosti. Prilagodite ili zamijenite dugme u Postavkama.\n\n"<annotation id="link">"Postavke"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Premjestite dugme do ivice da ga privremeno sakrijete"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Opozovi"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"Dugme za pristupačnost je sakriveno"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Prikazivanje dugmeta za pristupačnost dodirom"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Prečica <xliff:g id="FEATURE_NAME">%s</xliff:g> je uklonjena"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# prečica je uklonjena}one{# prečica je uklonjena}few{# prečice su uklonjene}other{# prečica je uklonjeno}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Pomjeranje gore lijevo"</string> diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml index d56e4f0d14c5..ab3bc8f9ccad 100644 --- a/packages/SystemUI/res/values-ca/strings.xml +++ b/packages/SystemUI/res/values-ca/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"No s\'ha pogut configurar el desbloqueig facial. Ves a Configuració per tornar-ho a provar."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Toca el sensor d\'empremtes digitals"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Prem la icona de desbloqueig per continuar"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"La cara no s\'ha reconegut. Usa l\'empremta digital."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"No s\'ha reconegut la cara"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Utilitza l\'empremta digital"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"Desbloqueig facial no està disponible"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth connectat."</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • S\'està carregant • Es completarà d\'aquí a <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Llisca cap a l\'esquerra per iniciar el tutorial de la comunitat"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Obre l\'editor de widgets"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personalitza"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Ignora"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Afegeix, suprimeix i reordena widgets en aquest espai"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Afegeix més widgets"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Mantén premut per personalitzar els widgets"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"Suprimeix"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Afegeix un widget"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Fet"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"Vols activar el Bluetooth?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"Per connectar el teclat amb la tauleta, primer has d\'activar el Bluetooth."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Activa"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Controls millorats per a notificacions"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Activat: basat en cares"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"Amb els controls de notificació millorats, pots establir un nivell d\'importància d\'entre 0 i 5 per a les notificacions d\'una aplicació. \n\n"<b>"Nivell 5"</b>" \n- Mostra les notificacions a la part superior de la llista \n- Permet la interrupció de la pantalla completa \n- Permet sempre la previsualització \n\n"<b>"Nivell 4"</b>" \n- No permet la interrupció de la pantalla completa \n- Permet sempre la previsualització \n\n"<b>"Nivell 3"</b>" \n- No permet la interrupció de la pantalla completa \n- No permet mai la previsualització \n\n"<b>"Nivell 2"</b>" \n- No permet la interrupció de la pantalla completa \n- No permet mai la previsualització \n- Les notificacions no poden emetre sons ni vibracions \n\n"<b>"Nivell 1"</b>" \n- No permet la interrupció de la pantalla completa \n- No permet mai la previsualització \n- No activa mai el so ni la vibració \n- Amaga les notificacions de la pantalla de bloqueig i de la barra d\'estat \n- Mostra les notificacions a la part inferior de la llista \n\n"<b>"Nivell 0"</b>" \n- Bloqueja totes les notificacions de l\'aplicació"</string> <string name="inline_done_button" msgid="6043094985588909584">"Fet"</string> <string name="inline_ok_button" msgid="603075490581280343">"Aplica"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Desactiva les notificacions"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"Configuració"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"Emmagatzematge"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"Suggeriments"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"Accessibilitat"</string> <string name="instant_apps" msgid="8337185853050247304">"Aplicacions instantànies"</string> <string name="instant_apps_title" msgid="8942706782103036910">"S\'està executant <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="instant_apps_message" msgid="6112428971833011754">"L\'aplicació s\'ha obert sense instal·lar-se."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Toca per obrir funcions d\'accessibilitat. Personalitza o substitueix el botó a Configuració.\n\n"<annotation id="link">"Mostra"</annotation>"."</string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Mou el botó a l\'extrem per amagar-lo temporalment"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Desfés"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"El botó d\'accessibilitat està amagat"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Toca per mostrar el botó d\'accessibilitat"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"S\'ha suprimit la drecera a <xliff:g id="FEATURE_NAME">%s</xliff:g>"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{S\'ha suprimit # drecera}many{S\'han suprimit # dreceres}other{S\'han suprimit # dreceres}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Mou a dalt a l\'esquerra"</string> diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml index 9c7143608678..4dd9d4fb5c69 100644 --- a/packages/SystemUI/res/values-cs/strings.xml +++ b/packages/SystemUI/res/values-cs/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Odemknutí obličejem se nepodařilo nastavit. Pokud to chcete zkusit znovu, přejděte do Nastavení."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Dotkněte se snímače otisků prstů"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Klepněte na ikonu odemknutí"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"Obličej nebyl rozpoznán. Použijte místo něj otisk prstu."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"Obličej nebyl rozpoznán"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Použijte otisk prstu"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"Odemknutí obličejem není k dispozici"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Rozhraní Bluetooth je připojeno."</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Nabíjení • Plně nabito za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Přejetím doleva spustíte komunitní výukový program"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Otevřít editor widgetů"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Přizpůsobit"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Zavřít"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"V tomto prostoru můžete přidávat a odstraňovat widgety a měnit jejich pořadí"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Přidat další widgety"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Dlouhým stisknutím můžete přizpůsobit widgety"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"Odstranit"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Přidat widget"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Hotovo"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"Zapnout Bluetooth?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"Chcete-li klávesnici připojit k tabletu, nejdříve musíte zapnout Bluetooth."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Zapnout"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Rozšířené ovládací prvky oznámení"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Zapnuto – podle obličeje"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"Rozšířené ovládací prvky oznámení umožňují nastavit úroveň důležitosti oznámení aplikace od 0 do 5. \n\n"<b>"Úroveň 5"</b>" \n– Zobrazit na začátku seznamu oznámení \n– Povolit vyrušení na celou obrazovku \n– Vždy zobrazit náhled \n\n"<b>"Úroveň 4"</b>" \n– Zabránit vyrušení na celou obrazovku \n– Vždy zobrazit náhled \n\n"<b>"Úroveň 3"</b>" \n– Zabránit vyrušení na celou obrazovku \n– Nikdy nezobrazovat náhled \n\n"<b>"Úroveň 2"</b>" \n– Zabránit vyrušení na celou obrazovku \n– Nikdy nezobrazovat náhled \n– Nikdy nevydávat žádný zvukový signál ani nevibrovat \n\n"<b>"Úroveň 1"</b>" \n– Zabránit vyrušení na celou obrazovku \n– Nikdy nezobrazovat náhled \n– Nikdy nevydávat zvukový signál ani nevibrovat \n– Skrýt na obrazovce uzamčení a stavového řádku \n– Zobrazovat na konci seznamu oznámení \n\n"<b>";Úroveň 0"</b>" \n– Blokovat všechna oznámení z aplikace"</string> <string name="inline_done_button" msgid="6043094985588909584">"Hotovo"</string> <string name="inline_ok_button" msgid="603075490581280343">"Použít"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Vypnout oznámení"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"Nastavit"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"Úložiště"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"Tipy"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"Přístupnost"</string> <string name="instant_apps" msgid="8337185853050247304">"Okamžité aplikace"</string> <string name="instant_apps_title" msgid="8942706782103036910">"Aplikace <xliff:g id="APP">%1$s</xliff:g> je spuštěna"</string> <string name="instant_apps_message" msgid="6112428971833011754">"Aplikace byla otevřena bez instalace."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Klepnutím otevřete funkce přístupnosti. Tlačítko lze upravit nebo nahradit v Nastavení.\n\n"<annotation id="link">"Nastavení"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Přesunutím tlačítka k okraji ho dočasně skryjete"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Vrátit zpět"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"Tlačítko přístupnosti je skryté"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Klepnutím zobrazíte tlačítko přístupnosti"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Zkratka pro <xliff:g id="FEATURE_NAME">%s</xliff:g> byla odstraněna"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{Byla odstraněna # zkratka}few{Byly odstraněny # zkratky}many{Bylo odstraněno # zkratky}other{Bylo odstraněno # zkratek}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Přesunout vlevo nahoru"</string> diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml index 06f9ff327d87..a2d17dfbac52 100644 --- a/packages/SystemUI/res/values-da/strings.xml +++ b/packages/SystemUI/res/values-da/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Ansigtsoplåsning kunne ikke konfigureres. Gå til Indstillinger for at prøve igen."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Sæt fingeren på fingeraftrykssensoren"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Tryk på oplåsningsikonet for at fortsætte"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"Ansigtet blev ikke genkendt. Brug fingeraftryk i stedet."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"Ansigt blev ikke genkendt"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Brug fingeraftryk i stedet"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"Ansigtsoplåsning er utilgængelig"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth tilsluttet."</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Oplader • Fuldt opladet om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Stryg mod venstre for at starte den fælles vejledning"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Åbn redigeringsværktøjet til widgets"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Tilpas"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Luk"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Tilføj, fjern og omorganiser widgets i dette rum"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Tilføj flere widgets"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Hold fingeren nede for at tilpasse widgets"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"Fjern"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Tilføj widget"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Udfør"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"Vil du slå Bluetooth til?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"Bluetooth skal være slået til, før du kan knytte dit tastatur til din tablet."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Slå til"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Kontrolelementer til notifikation om strøm"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Til – ansigtsbaseret"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"Med kontrolelementer til notifikationer om strøm kan du konfigurere et vigtighedsniveau fra 0 til 5 for en apps notifikationer. \n\n"<b>"Niveau 5"</b>\n"- Vis øverst på listen over notifikationer \n- Tillad afbrydelse af fuld skærm \n- Se altid smugkig \n\n"<b>"Niveau 4"</b>\n"- Ingen afbrydelse af fuld skærm \n- Se altid smugkig \n\n"<b>"Niveau 3"</b>\n"- Ingen afbrydelse af fuld skærm \n- Se aldrig smugkig \n\n"<b>"Niveau 2"</b>\n"- Ingen afbrydelse af fuld skærm \n Se aldrig smugkig \n- Ingen lyd og vibration \n\n"<b>"Niveau 1"</b>\n"- Ingen afbrydelse af fuld skærm \n- Se aldrig smugkig \n- Ingen lyd eller vibration \n- Skjul fra låseskærm og statusbjælke \n- Vis nederst på listen over notifikationer \n\n"<b>"Niveau 0"</b>\n"- Bloker alle notifikationer fra appen."</string> <string name="inline_done_button" msgid="6043094985588909584">"Udfør"</string> <string name="inline_ok_button" msgid="603075490581280343">"Anvend"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Deaktiver notifikationer"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"Konfiguration"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"Lagerplads"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"Tips"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"Hjælpefunktioner"</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> kører"</string> <string name="instant_apps_message" msgid="6112428971833011754">"En app blev åbnet uden at blive installeret."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Tryk for at åbne hjælpefunktioner. Tilpas eller erstat denne knap i Indstillinger.\n\n"<annotation id="link">"Se indstillingerne"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Flyt knappen til kanten for at skjule den midlertidigt"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Fortryd"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"Knappen til hjælpefunktioner er skjult"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Tryk for at se knappen til hjælpefunktioner"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Genvejen til <xliff:g id="FEATURE_NAME">%s</xliff:g> er fjernet"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# genvej er fjernet}one{# genvej er fjernet}other{# genveje er fjernet}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Flyt op til venstre"</string> diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml index 2acd2feaa879..bebedcebdc24 100644 --- a/packages/SystemUI/res/values-de/strings.xml +++ b/packages/SystemUI/res/values-de/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Die Entsperrung per Gesichtserkennung konnte nicht eingerichtet werden. Gehe zu den Einstellungen und versuche es noch einmal."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Berühre den Fingerabdrucksensor"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Tippe zum Fortfahren auf das Symbol „Entsperren“"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"Gesicht nicht erkannt. Verwende den Fingerabdruck."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"Gesicht nicht erkannt"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Fingerabdruck verwenden"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"Entsperrung per Gesichtserkennung nicht verfügbar"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Mit Bluetooth verbunden"</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Wird geladen • Voll in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Wische nach links, um das gemeinsame Tutorial zu starten"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Widget-Editor öffnen"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Anpassen"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Schließen"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Hier kannst du Widgets hinzufügen, entfernen und neu anordnen"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Weitere Widgets hinzufügen"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Lange drücken, um Widgets anzupassen"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"Entfernen"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Widget hinzufügen"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Fertig"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"Bluetooth aktivieren?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"Zum Verbinden von Tastatur und Tablet muss Bluetooth aktiviert sein."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Aktivieren"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Erweiterte Benachrichtigungseinstellungen"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"An – gesichtsbasiert"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"Mit den erweiterten Benachrichtigungseinstellungen kannst du für App-Benachrichtigungen eine Wichtigkeitsstufe von 0 bis 5 festlegen. \n\n"<b>"Stufe 5"</b>" \n- Auf der Benachrichtigungsleiste ganz oben anzeigen \n- Vollbildunterbrechung zulassen \n- Immer kurz einblenden \n\n"<b>"Stufe 4"</b>" \n- Keine Vollbildunterbrechung \n- Immer kurz einblenden \n\n"<b>"Stufe 3"</b>" \n- Keine Vollbildunterbrechung \n- Nie kurz einblenden \n\n"<b>"Stufe 2"</b>" \n- Keine Vollbildunterbrechung \n- Nie kurz einblenden \n- Weder Ton noch Vibration \n\n"<b>"Stufe 1"</b>" \n- Keine Vollbildunterbrechung \n- Nie kurz einblenden \n- Weder Ton noch Vibration \n- Auf Sperrbildschirm und Statusleiste verbergen \n- Auf der Benachrichtigungsleiste ganz unten anzeigen \n\n"<b>"Stufe 0"</b>" \n- Alle Benachrichtigungen der App sperren"</string> <string name="inline_done_button" msgid="6043094985588909584">"Fertig"</string> <string name="inline_ok_button" msgid="603075490581280343">"Anwenden"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Benachrichtigungen deaktivieren"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"Einrichtung"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"Speicher"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"Hinweise"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"Bedienungshilfen"</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> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Tippe, um die Bedienungshilfen aufzurufen. Du kannst diese Schaltfläche in den Einstellungen anpassen oder ersetzen.\n\n"<annotation id="link">"Zu den Einstellungen"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Durch Ziehen an den Rand wird die Schaltfläche zeitweise ausgeblendet"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Rückgängig machen"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"Schaltfläche „Bedienungshilfen“ ausgeblendet"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Tippen, um die Schaltfläche „Bedienungshilfen“ aufzurufen"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Verknüpfung für „<xliff:g id="FEATURE_NAME">%s</xliff:g>“ entfernt"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# Verknüpfung entfernt}other{# Verknüpfungen entfernt}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Nach oben links verschieben"</string> diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml index 79d350b16300..3c87ad90858e 100644 --- a/packages/SystemUI/res/values-el/strings.xml +++ b/packages/SystemUI/res/values-el/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Δεν ήταν δυνατή η ρύθμιση για το Ξεκλείδωμα με το πρόσωπο. Μεταβείτε στις Ρυθμίσεις και δοκιμάστε ξανά."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Αγγίξτε τον αισθητήρα δακτυλικού αποτυπώματος"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Πατήστε το εικονίδιο ξεκλειδώματος για συνέχεια"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"Δεν αναγνωρίστηκε. Χρήση δακτυλικού αποτυπώματος."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"Δεν αναγνωρίστηκε"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Χρησιμ. δακτυλ. αποτύπ."</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"Ξεκλ. με πρόσωπο μη διαθ."</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Το Bluetooth είναι συνδεδεμένο."</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Φόρτιση • Πλήρης φόρτιση σε <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Σύρετε προς τα αριστερά για να ξεκινήσετε τον κοινόχρηστο οδηγό"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Άνοιγμα προγράμ. επεξεργασίας γραφικών στοιχείων"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Προσαρμογή"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Παράβλεψη"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Προσθήκη, κατάργηση και αναδιάταξη των γραφικών στοιχείων σε αυτόν τον χώρο"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Προσθήκη περισσότερων γραφικών στοιχείων"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Παρατεταμένο πάτημα για προσαρμογή γραφ. στοιχείων"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"Κατάργηση"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Προσθήκη γραφικού στοιχείου"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Τέλος"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"Ενεργοποίηση Bluetooth;"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"Για να συνδέσετε το πληκτρολόγιο με το tablet σας, θα πρέπει πρώτα να ενεργοποιήσετε το Bluetooth."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Ενεργοποίηση"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Στοιχεία ελέγχου ειδοποίησης ισχύος"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Ενεργό - Βάσει προσώπου"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"Με τα στοιχεία ελέγχου ειδοποίησης ισχύος, μπορείτε να ορίσετε ένα επίπεδο βαρύτητας από 0 έως 5 για τις ειδοποιήσεις μιας εφαρμογής. \n\n"<b>"Επίπεδο 5"</b>" \n- Εμφάνιση στην κορυφή της λίστας ειδοποιήσεων \n- Να επιτρέπεται η διακοπή πλήρους οθόνης \n- Να γίνεται πάντα σύντομη προβολή \n\n"<b>"Επίπεδο 4"</b>" \n- Αποτροπή διακοπής πλήρους οθόνης \n- Να γίνεται πάντα σύντομη προβολή \n\n"<b>"Επίπεδο 3"</b>" \n- Αποτροπή διακοπής πλήρους οθόνης \n- Να μην γίνεται ποτέ σύντομη προβολή \n\n"<b>"Επίπεδο 2"</b>" \n- Αποτροπή διακοπής πλήρους οθόνης \n- Να μην γίνεται ποτέ σύντομη προβολή \n- Να μην χρησιμοποιείται ποτέ ήχος και δόνηση \n\n"<b>"Επίπεδο 1"</b>" \n- Αποτροπή διακοπής πλήρους οθόνης \n- Να μην γίνεται ποτέ σύντομη προβολή \n- Να μην χρησιμοποιείται ποτέ ήχος και δόνηση \n- Απόκρυψη από την οθόνη κλειδώματος και τη γραμμή κατάστασης \n- Εμφάνιση στο κάτω μέρος της λίστας ειδοποιήσεων \n\n"<b>"Επίπεδο 0"</b>" \n- Αποκλεισμός όλων των ειδοποιήσεων από την εφαρμογή"</string> <string name="inline_done_button" msgid="6043094985588909584">"Τέλος"</string> <string name="inline_ok_button" msgid="603075490581280343">"Εφαρμογή"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Απενεργοποίηση ειδοποιήσεων"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"Ρύθμιση"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"Αποθηκευτικός χώρος"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"Συμβουλές"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"Προσβασιμότητα"</string> <string name="instant_apps" msgid="8337185853050247304">"Instant Εφαρμογές"</string> <string name="instant_apps_title" msgid="8942706782103036910">"Η εφαρμογή <xliff:g id="APP">%1$s</xliff:g> εκτελείται"</string> <string name="instant_apps_message" msgid="6112428971833011754">"Η εφαρμογή άνοιξε χωρίς να έχει εγκατασταθεί."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Πατήστε για άνοιγμα των λειτουργιών προσβασιμότητας. Προσαρμόστε ή αντικαταστήστε το κουμπί στις Ρυθμίσεις.\n\n"<annotation id="link">"Προβολή ρυθμίσεων"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Μετακινήστε το κουμπί στο άκρο για προσωρινή απόκρυψη"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Αναίρεση"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"Έχει γίνει απόκρυψη του κουμπιού προσβασιμότητας"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Πατήστε για εμφάνιση του κουμπιού προσβασιμότητας"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Η συντόμευση <xliff:g id="FEATURE_NAME">%s</xliff:g> καταργήθηκε"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{Καταργήθηκε # συντόμευση}other{Καταργήθηκαν # συντομεύσεις}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Μετακίνηση επάνω αριστερά"</string> diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml index afd2e728aa68..cbdc26fbe012 100644 --- a/packages/SystemUI/res/values-en-rAU/strings.xml +++ b/packages/SystemUI/res/values-en-rAU/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Couldn\'t set up Face Unlock. Go to Settings to try again."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Touch the fingerprint sensor"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Press the unlock icon to continue"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"Face not recognised. Use fingerprint instead."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"Face not recognised"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Use fingerprint instead"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"Face Unlock unavailable"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth connected."</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Swipe left to start the communal tutorial"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Open the widget editor"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Customise"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Dismiss"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Add, remove and reorder your widgets in this space"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Add more widgets"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Long press to customise widgets"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"Remove"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Add widget"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Done"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"Turn on Bluetooth?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"To connect your keyboard with your tablet, you first have to turn on Bluetooth."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Turn on"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Power notification controls"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"On – Face-based"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"With power notification controls, you can set an importance level from 0 to 5 for an app\'s notifications. \n\n"<b>"Level 5"</b>" \n- Show at the top of the notification list \n- Allow full screen interruption \n- Always peek \n\n"<b>"Level 4"</b>" \n- Prevent full screen interruption \n- Always peek \n\n"<b>"Level 3"</b>" \n- Prevent full screen interruption \n- Never peek \n\n"<b>"Level 2"</b>" \n- Prevent full screen interruption \n- Never peek \n- Never make sound and vibration \n\n"<b>"Level 1"</b>" \n- Prevent full screen interruption \n- Never peek \n- Never make sound or vibrate \n- Hide from lock screen and status bar \n- Show at the bottom of the notification list \n\n"<b>"Level 0"</b>" \n- Block all notifications from the app"</string> <string name="inline_done_button" msgid="6043094985588909584">"Done"</string> <string name="inline_ok_button" msgid="603075490581280343">"Apply"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Turn off notifications"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"Setup"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"Storage"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"Hints"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"Accessibility"</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> running"</string> <string name="instant_apps_message" msgid="6112428971833011754">"App opened without being installed."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Tap to open accessibility features. Customise or replace this button in Settings.\n\n"<annotation id="link">"View settings"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Move button to the edge to hide it temporarily"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Undo"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"Accessibility button hidden"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Tap to show Accessibility button"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> shortcut removed"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# shortcut removed}other{# shortcuts removed}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Move top left"</string> diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml index a0000efbd607..da14f53675c7 100644 --- a/packages/SystemUI/res/values-en-rCA/strings.xml +++ b/packages/SystemUI/res/values-en-rCA/strings.xml @@ -604,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"Turn on Bluetooth?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"To connect your keyboard with your tablet, you first have to turn on Bluetooth."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Turn on"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Power notification controls"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"On - Face-based"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"With power notification controls, you can set an importance level from 0 to 5 for an app\'s notifications. \n\n"<b>"Level 5"</b>" \n- Show at the top of the notification list \n- Allow full screen interruption \n- Always peek \n\n"<b>"Level 4"</b>" \n- Prevent full screen interruption \n- Always peek \n\n"<b>"Level 3"</b>" \n- Prevent full screen interruption \n- Never peek \n\n"<b>"Level 2"</b>" \n- Prevent full screen interruption \n- Never peek \n- Never make sound and vibration \n\n"<b>"Level 1"</b>" \n- Prevent full screen interruption \n- Never peek \n- Never make sound or vibrate \n- Hide from lock screen and status bar \n- Show at the bottom of the notification list \n\n"<b>"Level 0"</b>" \n- Block all notifications from the app"</string> <string name="inline_done_button" msgid="6043094985588909584">"Done"</string> <string name="inline_ok_button" msgid="603075490581280343">"Apply"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Turn off notifications"</string> diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml index afd2e728aa68..cbdc26fbe012 100644 --- a/packages/SystemUI/res/values-en-rGB/strings.xml +++ b/packages/SystemUI/res/values-en-rGB/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Couldn\'t set up Face Unlock. Go to Settings to try again."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Touch the fingerprint sensor"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Press the unlock icon to continue"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"Face not recognised. Use fingerprint instead."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"Face not recognised"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Use fingerprint instead"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"Face Unlock unavailable"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth connected."</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Swipe left to start the communal tutorial"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Open the widget editor"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Customise"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Dismiss"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Add, remove and reorder your widgets in this space"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Add more widgets"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Long press to customise widgets"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"Remove"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Add widget"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Done"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"Turn on Bluetooth?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"To connect your keyboard with your tablet, you first have to turn on Bluetooth."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Turn on"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Power notification controls"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"On – Face-based"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"With power notification controls, you can set an importance level from 0 to 5 for an app\'s notifications. \n\n"<b>"Level 5"</b>" \n- Show at the top of the notification list \n- Allow full screen interruption \n- Always peek \n\n"<b>"Level 4"</b>" \n- Prevent full screen interruption \n- Always peek \n\n"<b>"Level 3"</b>" \n- Prevent full screen interruption \n- Never peek \n\n"<b>"Level 2"</b>" \n- Prevent full screen interruption \n- Never peek \n- Never make sound and vibration \n\n"<b>"Level 1"</b>" \n- Prevent full screen interruption \n- Never peek \n- Never make sound or vibrate \n- Hide from lock screen and status bar \n- Show at the bottom of the notification list \n\n"<b>"Level 0"</b>" \n- Block all notifications from the app"</string> <string name="inline_done_button" msgid="6043094985588909584">"Done"</string> <string name="inline_ok_button" msgid="603075490581280343">"Apply"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Turn off notifications"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"Setup"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"Storage"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"Hints"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"Accessibility"</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> running"</string> <string name="instant_apps_message" msgid="6112428971833011754">"App opened without being installed."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Tap to open accessibility features. Customise or replace this button in Settings.\n\n"<annotation id="link">"View settings"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Move button to the edge to hide it temporarily"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Undo"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"Accessibility button hidden"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Tap to show Accessibility button"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> shortcut removed"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# shortcut removed}other{# shortcuts removed}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Move top left"</string> diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml index afd2e728aa68..cbdc26fbe012 100644 --- a/packages/SystemUI/res/values-en-rIN/strings.xml +++ b/packages/SystemUI/res/values-en-rIN/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Couldn\'t set up Face Unlock. Go to Settings to try again."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Touch the fingerprint sensor"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Press the unlock icon to continue"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"Face not recognised. Use fingerprint instead."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"Face not recognised"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Use fingerprint instead"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"Face Unlock unavailable"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth connected."</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Charging • Full in <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Swipe left to start the communal tutorial"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Open the widget editor"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Customise"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Dismiss"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Add, remove and reorder your widgets in this space"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Add more widgets"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Long press to customise widgets"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"Remove"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Add widget"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Done"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"Turn on Bluetooth?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"To connect your keyboard with your tablet, you first have to turn on Bluetooth."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Turn on"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Power notification controls"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"On – Face-based"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"With power notification controls, you can set an importance level from 0 to 5 for an app\'s notifications. \n\n"<b>"Level 5"</b>" \n- Show at the top of the notification list \n- Allow full screen interruption \n- Always peek \n\n"<b>"Level 4"</b>" \n- Prevent full screen interruption \n- Always peek \n\n"<b>"Level 3"</b>" \n- Prevent full screen interruption \n- Never peek \n\n"<b>"Level 2"</b>" \n- Prevent full screen interruption \n- Never peek \n- Never make sound and vibration \n\n"<b>"Level 1"</b>" \n- Prevent full screen interruption \n- Never peek \n- Never make sound or vibrate \n- Hide from lock screen and status bar \n- Show at the bottom of the notification list \n\n"<b>"Level 0"</b>" \n- Block all notifications from the app"</string> <string name="inline_done_button" msgid="6043094985588909584">"Done"</string> <string name="inline_ok_button" msgid="603075490581280343">"Apply"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Turn off notifications"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"Setup"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"Storage"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"Hints"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"Accessibility"</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> running"</string> <string name="instant_apps_message" msgid="6112428971833011754">"App opened without being installed."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Tap to open accessibility features. Customise or replace this button in Settings.\n\n"<annotation id="link">"View settings"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Move button to the edge to hide it temporarily"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Undo"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"Accessibility button hidden"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Tap to show Accessibility button"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> shortcut removed"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# shortcut removed}other{# shortcuts removed}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Move top left"</string> diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml index 835cf38556bc..aec29d8c4a1b 100644 --- a/packages/SystemUI/res/values-en-rXC/strings.xml +++ b/packages/SystemUI/res/values-en-rXC/strings.xml @@ -604,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"Turn on Bluetooth?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"To connect your keyboard with your tablet, you first have to turn on Bluetooth."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Turn on"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Power notification controls"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"On - Face-based"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"With power notification controls, you can set an importance level from 0 to 5 for an app\'s notifications. \n\n"<b>"Level 5"</b>" \n- Show at the top of the notification list \n- Allow full screen interruption \n- Always peek \n\n"<b>"Level 4"</b>" \n- Prevent full screen interruption \n- Always peek \n\n"<b>"Level 3"</b>" \n- Prevent full screen interruption \n- Never peek \n\n"<b>"Level 2"</b>" \n- Prevent full screen interruption \n- Never peek \n- Never make sound and vibration \n\n"<b>"Level 1"</b>" \n- Prevent full screen interruption \n- Never peek \n- Never make sound or vibrate \n- Hide from lock screen and status bar \n- Show at the bottom of the notification list \n\n"<b>"Level 0"</b>" \n- Block all notifications from the app"</string> <string name="inline_done_button" msgid="6043094985588909584">"Done"</string> <string name="inline_ok_button" msgid="603075490581280343">"Apply"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Turn off notifications"</string> diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml index a12c574c2c37..6dcc40a11d33 100644 --- a/packages/SystemUI/res/values-es-rUS/strings.xml +++ b/packages/SystemUI/res/values-es-rUS/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"No se pudo configurar el desbloqueo facial. Ve a Configuración para volver a intentarlo."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Toca el sensor de huellas dactilares"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Presiona el ícono de desbloqueo para continuar"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"No se reconoció el rostro. Usa la huella dactilar."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"No se reconoció el rostro"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Usa la huella dactilar"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"Desbloqueo facial no disponible"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth conectado"</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Cargando • Se completará en <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Desliza el dedo a la izquierda para iniciar el instructivo comunal"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Abrir el editor de widget"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personalizar"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Descartar"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Agrega, quita y reordena tus widgets en este espacio"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Agregar más widgets"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Mantén presionado para personalizar los widgets"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"Quitar"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Agregar widget"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Listo"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"¿Activar Bluetooth?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"Para conectar el teclado con la tablet, primero debes activar Bluetooth."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Activar"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Controles de activación de notificaciones"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Activa - En función del rostro"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"Con los controles de activación de notificaciones, puedes establecer un nivel de importancia para las notificaciones de una app. \n\n"<b>"Nivel 5"</b>" \n- Mostrar en la parte superior de la lista de notificaciones. \n- Permitir interrupción en la pantalla completa. \n- Mostrar siempre. \n\n"<b>"Nivel 4"</b>" \n- No permitir interrupción en la pantalla completa. \n- Mostrar siempre. \n\n"<b>"Nivel 3"</b>" \n- No permitir interrupción en la pantalla completa. \n- No mostrar. \n\n"<b>"Nivel 2"</b>" \n- No permitir interrupción en la pantalla completa. \n- No mostrar. \n- No sonar ni vibrar. \n\n"<b>"Nivel 1"</b>" \n- No permitir interrupción en la pantalla completa. \n- No mostrar. \n- No sonar ni vibrar. \n- Ocultar de la pantalla bloqueada y la barra de estado. \n- Mostrar al final de la lista de notificaciones. \n\n"<b>"Nivel 0"</b>" \n- Bloquear todas las notificaciones de la app."</string> <string name="inline_done_button" msgid="6043094985588909584">"Listo"</string> <string name="inline_ok_button" msgid="603075490581280343">"Aplicar"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Desactivar notificaciones"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"Configuración"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"Almacenamiento"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"Sugerencias"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"Accesibilidad"</string> <string name="instant_apps" msgid="8337185853050247304">"Apps instantáneas"</string> <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> en ejecución"</string> <string name="instant_apps_message" msgid="6112428971833011754">"La app se abrió sin instalarse."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Presiona para abrir las funciones de accesibilidad. Personaliza o cambia botón en Config.\n\n"<annotation id="link">"Ver config"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Mueve el botón hacia el borde para ocultarlo temporalmente"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Deshacer"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"Botón de accesibilidad oculto"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Presiona para ver el botón de accesibilidad"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Se quitó el acceso directo a <xliff:g id="FEATURE_NAME">%s</xliff:g>"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{Se quitó # acceso directo}many{Se quitaron # accesos directos}other{Se quitaron # accesos directos}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Mover arriba a la izquierda"</string> diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml index 765f2e3e9479..aecf5b1f0c44 100644 --- a/packages/SystemUI/res/values-es/strings.xml +++ b/packages/SystemUI/res/values-es/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"No se ha podido configurar Desbloqueo facial. Ve a Ajustes e inténtalo de nuevo."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Toca el sensor de huellas digitales"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Pulsa el icono de desbloquear para continuar"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"Cara no reconocida. Usa la huella digital."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"Cara no reconocida"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Usa la huella digital"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"Desbloqueo facial no disponible"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth conectado"</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Cargando • Carga completa en <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Desliza hacia la izquierda para iniciar el tutorial de la comunidad"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Abrir editor de widgets"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personalizar"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Cerrar"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Añade, elimina y reordena tus widgets en este espacio"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Añade más widgets"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Mantén pulsado para personalizar los widgets"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"Quitar"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Añadir widget"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Hecho"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"¿Activar Bluetooth?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"Para poder conectar tu teclado a tu tablet, debes activar el Bluetooth."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Activar"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Controles de energía de las notificaciones"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Activado: basado en caras"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"Los controles de energía de las notificaciones permiten establecer un nivel de importancia de 0 a 5 para las notificaciones de las aplicaciones. \n\n"<b>"Nivel 5"</b>" \n- Mostrar en la parte superior de la lista de notificaciones \n- Permitir interrumpir en el modo de pantalla completa \n- Mostrar siempre \n\n"<b>"Nivel 4"</b>" \n- Evitar interrumpir en el modo de pantalla completa \n- Mostrar siempre \n\n"<b>"Nivel 3"</b>" \n- Evitar interrumpir en el modo de pantalla completa \n- No mostrar nunca \n\n"<b>"Nivel 2"</b>" \n- Evitar interrumpir en el modo de pantalla completa\n- No mostrar nunca \n- No emitir sonido ni vibrar nunca \n\n"<b>"Nivel 1"</b>" \n- Evitar interrumpir en el modo de pantalla completa \n- No mostrar nunca \n- No emitir sonido ni vibrar nunca \n- Ocultar de la pantalla de bloqueo y de la barra de estado \n- Mostrar en la parte inferior de la lista de notificaciones \n\n"<b>"Nivel 0"</b>" \n- Bloquear todas las notificaciones de la aplicación"</string> <string name="inline_done_button" msgid="6043094985588909584">"Hecho"</string> <string name="inline_ok_button" msgid="603075490581280343">"Aplicar"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Desactivar notificaciones"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"Configuración"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"Almacenamiento"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"Sugerencias"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"Accesibilidad"</string> <string name="instant_apps" msgid="8337185853050247304">"Aplicaciones Instantáneas"</string> <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> se está ejecutando"</string> <string name="instant_apps_message" msgid="6112428971833011754">"La aplicación se ha abierto sin instalarse."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Toca para abrir funciones de accesibilidad. Personaliza o sustituye este botón en Ajustes.\n\n"<annotation id="link">"Ver ajustes"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Mueve el botón hacia el borde para ocultarlo temporalmente"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Deshacer"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"Botón de accesibilidad oculto"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Toca para que se muestre el botón de accesibilidad"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Acceso directo a <xliff:g id="FEATURE_NAME">%s</xliff:g> quitado"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# acceso directo eliminado}many{# accesos directos eliminados}other{# accesos directos eliminados}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Mover arriba a la izquierda"</string> diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml index 249e45f0c650..edfb5bebf2fd 100644 --- a/packages/SystemUI/res/values-et/strings.xml +++ b/packages/SystemUI/res/values-et/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Näoga avamist ei õnnestunud seadistada. Avage seaded ja proovige uuesti."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Puudutage sõrmejäljeandurit"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Jätkamiseks vajutage avamise ikooni"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"Nägu ei tuvastatud. Kasutage sõrmejälge."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"Nägu ei tuvastatud"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Kasutage sõrmejälge"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"Näoga avamine pole saadaval"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth on ühendatud."</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laadimine • Täis <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> pärast"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Ühise õpetuse käivitamiseks pühkige vasakule"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Vidina redaktori avamine"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Kohandage"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Loobuge"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Lisage ja eemaldage selles ruumis oma vidinaid ning muutke nende järjestust"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Lisage rohkem vidinaid"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Vajutage pikalt vidinate kohandamiseks"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"Eemalda"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Lisa vidin"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Valmis"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"Kas lülitada Bluetooth sisse?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"Klaviatuuri ühendamiseks tahvelarvutiga peate esmalt Bluetoothi sisse lülitama."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Lülita sisse"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Toite märguannete juhtnupud"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Sees – näopõhine"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"Toite märguannete juhtnuppudega saate määrata rakenduse märguannete tähtsuse taseme vahemikus 0–5. \n\n"<b>"5. tase"</b>" \n- Kuva märguannete loendi ülaosas\n- Luba täisekraanil häirimine \n- Kuva alati ekraani servas \n\n"<b>"4. tase"</b>" \n- Keela täisekraanil häirimine \n- Kuva alati ekraani servas \n\n"<b>"3. tase"</b>" \n- Keela täisekraanil häirimine \n- Ära kunagi kuva ekraani servas \n\n"<b>"2. tase"</b>" \n- Keela täisekraanil häirimine \n- Ära kunagi kuva ekraani servas \n- Ära kunagi helise ega vibreeri \n\n"<b>"1. tase"</b>" \n- Keela täisekraanil häirimine \n- Ära kunagi kuva ekraani servas \n- Ära kunagi helise ega vibreeri \n- Peida lukustuskuval ja olekuribal \n- Kuva märguannete loendi allosas \n\n"<b>"Tase 0"</b>" \n- Blokeeri kõik rakenduse märguanded"</string> <string name="inline_done_button" msgid="6043094985588909584">"Valmis"</string> <string name="inline_ok_button" msgid="603075490581280343">"Rakenda"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Lülita märguanded välja"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"Seadistamine"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"Salvestusruum"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"Vihjed"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"Juurdepääsetavus"</string> <string name="instant_apps" msgid="8337185853050247304">"Installimata avatavad rakendused"</string> <string name="instant_apps_title" msgid="8942706782103036910">"Rakendus <xliff:g id="APP">%1$s</xliff:g> töötab"</string> <string name="instant_apps_message" msgid="6112428971833011754">"Rakendus avati installimata."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Puudutage juurdepääsufunktsioonide avamiseks. Kohandage nuppu või asendage see seadetes.\n\n"<annotation id="link">"Kuva seaded"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Teisaldage nupp serva, et see ajutiselt peita"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Võta tagasi"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"Juurdepääsetavuse nupp on peidetud"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Puudutage juurdepääsetavuse nupu kuvamiseks"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Funktsiooni <xliff:g id="FEATURE_NAME">%s</xliff:g> otsetee eemaldati"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# otsetee eemaldati}other{# otseteed eemaldati}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Teisalda üles vasakule"</string> diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml index 1a0d482a14a9..7fe37b46e9c5 100644 --- a/packages/SystemUI/res/values-eu/strings.xml +++ b/packages/SystemUI/res/values-eu/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Ezin izan da konfiguratu aurpegi bidez desblokeatzeko eginbidea. Berriro saiatzeko, joan ezarpenetara."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Sakatu hatz-marken sentsorea"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Aurrera egiteko, sakatu desblokeatzeko ikonoa"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"Ez da ezagutu aurpegia. Erabili hatz-marka."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"Ez da ezagutu aurpegia"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Erabili hatz-marka"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"Aurpegi bidez desblokeatzeko eginbidea ez dago erabilgarri"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetootha konektatuta."</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Kargatzen • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> guztiz kargatu arte"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Tutorial komuna hasteko, pasatu hatza ezkerrera"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Ireki widget-editorea"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Pertsonalizatu"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Baztertu"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Gehitu eta kendu eremu honetako widgetak, edo aldatu haien ordena"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Gehitu widget gehiago"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Widgetak pertsonalizatzeko, sakatu luze"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"Kendu"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Gehitu widget bat"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Eginda"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"Bluetooth eginbidea aktibatu nahi duzu?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"Teklatua tabletara konektatzeko, Bluetooth eginbidea aktibatu behar duzu."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Aktibatu"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Bateria-mailaren arabera jakinarazpenak kontrolatzeko aukerak"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Aktibatuta: aurpegian oinarrituta"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"Bateria-mailaren arabera jakinarazpenak kontrolatzeko aukerekin, 0 eta 5 bitarteko garrantzi-mailetan sailka ditzakezu aplikazioen jakinarazpenak. \n\n"<b>"5. maila"</b>" \n- Erakutsi jakinarazpenen zerrendaren goialdean. \n- Baimendu etetea pantaila osoko moduan zaudenean. \n- Agerrarazi beti jakinarazpenak. \n\n"<b>"4. maila"</b>" \n- Galarazi etetea pantaila osoko moduan zaudenean. \n- Agerrarazi beti jakinarazpenak. \n\n"<b>"3. maila"</b>" \n- Galarazi etetea pantaila osoko moduan zaudenean. \n- Ez agerrarazi jakinarazpenik inoiz. \n\n"<b>"2. maila"</b>" \n- Galarazi etetea pantaila osoko moduan zaudenean. \n- Ez agerrarazi jakinarazpenik inoiz. \n- Ez egin soinurik edo dardararik inoiz. \n\n"<b>"1. maila"</b>" \n- Galarazi etetea pantaila osoko moduan zaudenean. \n- Ez agerrarazi jakinarazpenik inoiz. \n- Ez egin soinurik edo dardararik inoiz. \n- Ezkutatu pantaila blokeatutik eta egoera-barratik. \n- Erakutsi jakinarazpenen zerrendaren behealdean. \n\n"<b>"0. maila"</b>" \n- Blokeatu aplikazioaren jakinarazpen guztiak."</string> <string name="inline_done_button" msgid="6043094985588909584">"Eginda"</string> <string name="inline_ok_button" msgid="603075490581280343">"Aplikatu"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Desaktibatu jakinarazpenak"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"Konfigurazioa"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"Memoria"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"Aholkuak"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"Erabilerraztasuna"</string> <string name="instant_apps" msgid="8337185853050247304">"Zuzeneko aplikazioak"</string> <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> abian da"</string> <string name="instant_apps_message" msgid="6112428971833011754">"Ezer instalatu gabe ireki da aplikazioa."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Erabilerraztasun-eginbideak irekitzeko, sakatu hau. Ezarpenetan pertsonalizatu edo ordez dezakezu botoia.\n\n"<annotation id="link">"Ikusi ezarpenak"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Eraman botoia ertzera aldi baterako ezkutatzeko"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Desegin"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"Erabilerraztasuna botoia ezkutatuta dago"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Erabilerraztasuna botoia erakusteko, sakatu hau"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Kendu da lasterbidea (<xliff:g id="FEATURE_NAME">%s</xliff:g>)"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# lasterbide kendu da}other{# lasterbide kendu dira}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Eraman goialdera, ezkerretara"</string> diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml index b77c94972fb8..485009d1d6bc 100644 --- a/packages/SystemUI/res/values-fa/strings.xml +++ b/packages/SystemUI/res/values-fa/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"«قفلگشایی با چهره» راهاندازی نشد. برای امتحان مجدد، به «تنظیمات» بروید."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"حسگر اثر انگشت را لمس کنید"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"برای ادامه، نماد قفلگشایی را فشار دهید"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"چهره شناسایی نشد. درعوض از اثر انگشت استفاده کنید."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"چهره شناسایی نشد"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"از اثر انگشت استفاده کنید"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"«قفلگشایی با چهره» دردسترس نیست"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"بلوتوث متصل است."</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • درحال شارژ شدن • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> تا شارژ کامل"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"برای شروع آموزش گامبهگام عمومی، تند بهچپ بکشید"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"باز کردن ویرایشگر ابزارک"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"سفارشیسازی"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"بستن"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"افزودن، برداشتن، و تغییر ترتیب ابزارکها در این فضا"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"افزودن ابزارکهای بیشتر"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"برای سفارشیسازی ابزارکها، فشار طولانی دهید"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"برداشتن"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"افزودن ابزارک"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"تمام"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"بلوتوث روشن شود؟"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"برای مرتبط کردن صفحهکلید با رایانه لوحی، ابتدا باید بلوتوث را روشن کنید."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"روشن کردن"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"کنترلهای قدرتمند اعلان"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"روشن - براساس چهره"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"با کنترلهای قدرتمند اعلان میتوانید سطح اهمیت اعلانهای هر برنامه را از ۰ تا ۵ تعیین کنید. \n\n"<b>"سطح ۵"</b>" \n- در صدر فهرست اعلانها نشان داده میشود \n- وقفه برای نمایش تمامصفحه مجاز است \n- همیشه اجمالی نشان داده میشود \n\n"<b>"سطح ۴"</b>" \n- وقفه برای نمایش تمامصفحه مجاز نیست \n- همیشه اجمالی نشان داده میشود \n\n"<b>"سطح ۳"</b>" \n- وقفه برای نمایش تمامصفحه مجاز نیست \n- هیچوقت اجمالی نشان داده نمیشود \n\n"<b>"سطح ۲"</b>" \n- وقفه برای نمایش تمامصفحه مجاز نیست \n- هیچوقت اجمالی نشان داده نمیشود \n- هیچوقت صدا و لرزش ایجاد نمیکند \n\n"<b>"سطح ۱"</b>" \n- نمایش تمام صفحه مجاز نیست \n- هیچوقت اجمالی نشان داده نمیشود \n- هیچوقت صدا یا لرزش ایجاد نمیکند \n- در صفحه قفل و نوار وضعیت پنهان است \n- در پایین فهرست اعلانها نشان داده میشود \n\n"<b>"سطح ۰"</b>" \n- همه اعلانهای این برنامه مسدود است"</string> <string name="inline_done_button" msgid="6043094985588909584">"تمام"</string> <string name="inline_ok_button" msgid="603075490581280343">"اعمال"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"خاموش کردن اعلانها"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"راهاندازی"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"فضای ذخیرهسازی"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"نکات"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"دسترسپذیری"</string> <string name="instant_apps" msgid="8337185853050247304">"برنامههای فوری"</string> <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> درحال اجرا"</string> <string name="instant_apps_message" msgid="6112428971833011754">"برنامه بدون نصب شدن باز شد."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"برای باز کردن ویژگیهای دسترسپذیری ضربه بزنید. در تنظیمات این دکمه را سفارشی یا جایگزین کنید\n\n"<annotation id="link">"تنظیمات"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"برای پنهان کردن موقتی دکمه، آن را به لبه ببرید"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"واگرد"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"دکمه دسترسپذیری پنهان شده است"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"برای نمایش دکمه دسترسپذیری ضربه بزنید"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"میانبر «<xliff:g id="FEATURE_NAME">%s</xliff:g>» برداشته شد"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{میانبر «#» برداشته شد}one{میانبر «#» برداشته شد}other{میانبر «#» برداشته شد}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"انتقال به بالا سمت راست"</string> diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml index b764e07dea93..e65d7e07f036 100644 --- a/packages/SystemUI/res/values-fi/strings.xml +++ b/packages/SystemUI/res/values-fi/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Kasvojentunnistusavauksen käyttöönotto epäonnistui. Siirry asetuksiin ja yritä uudelleen."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Kosketa sormenjälkitunnistinta"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Jatka lukituksen avauskuvakkeella"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"Kasvoja ei tunnistettu. Käytä sormenjälkeä."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"Kasvoja ei tunnistettu"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Käytä sormenjälkeä"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"Kasvojentunnistusavaus ei ole saatavilla"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth yhdistetty."</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Latautuu • Täynnä <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> päästä"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Aloita yhteisöesittely pyyhkäisemällä vasemmalle"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Avaa widgetien muokkaaja"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Muokkaa"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Hylkää"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Lisää, poista ja järjestä widgetejäsi uudelleen tässä tilassa"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Lisää widgetejä"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Yksilöi widgetit pitkällä painalluksella"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"Poista"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Lisää widget"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Valmis"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"Otetaanko Bluetooth käyttöön?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"Jotta voit yhdistää näppäimistön tablettiisi, sinun on ensin otettava Bluetooth käyttöön."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Ota käyttöön"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Ilmoitusten tehohallinta"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Päällä – kasvojen perusteella"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"Ilmoitusten tehohallinnan avulla voit määrittää sovelluksen ilmoituksille tärkeystason väliltä 0–5. \n\n"<b>"Taso 5"</b>" \n– Ilmoitukset näytetään ilmoitusluettelon yläosassa \n– Näkyminen koko näytön tilassa sallitaan \n– Ilmoitukset kurkistavat aina näytölle\n\n"<b>"Taso 4"</b>" \n– Näkyminen koko näytön tilassa estetään \n– Ilmoitukset kurkistavat aina näytölle \n\n"<b>"Taso 3"</b>" \n– Näkyminen koko näytön tilassa estetään \n– Ei kurkistamista \n\n"<b>"Taso 2"</b>" \n– Näkyminen koko näytön tilassa estetään \n– Ei kurkistamista \n– Ei ääniä eikä värinää \n\n"<b>"Taso 1"</b>" \n– Näkyminen koko näytön tilassa estetään \n– Ei kurkistamista \n– Ei ääniä eikä värinää \n– Ilmoitukset piilotetaan lukitusnäytöltä ja tilapalkista \n– Ilmoitukset näytetään ilmoitusluettelon alaosassa \n\n"<b>"Taso 0"</b>" \n– Kaikki sovelluksen ilmoitukset estetään"</string> <string name="inline_done_button" msgid="6043094985588909584">"Valmis"</string> <string name="inline_ok_button" msgid="603075490581280343">"Käytä"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Poista ilmoitukset käytöstä"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"Määritys"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"Tallennustila"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"Vihjeet"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"Saavutettavuus"</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> on käynnissä"</string> <string name="instant_apps_message" msgid="6112428971833011754">"Sovellus avattiin ilman asennusta."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Avaa esteettömyysominaisuudet napauttamalla. Yksilöi tai vaihda painike asetuksista.\n\n"<annotation id="link">"Avaa asetukset"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Piilota painike tilapäisesti siirtämällä se reunaan"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Kumoa"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"Saavutettavuuspainike piilotettu"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Tuo saavutettavuuspainike esiin napauttamalla"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Pikanäppäin (<xliff:g id="FEATURE_NAME">%s</xliff:g>) poistettu"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# pikanäppäin poistettu}other{# pikanäppäintä poistettu}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Siirrä vasempaan yläreunaan"</string> diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml index 68f69a602e2a..557b9b8bbe13 100644 --- a/packages/SystemUI/res/values-fr-rCA/strings.xml +++ b/packages/SystemUI/res/values-fr-rCA/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Impossible de configurer le Déverrouillage par reconnaissance faciale. Accédez au menu Paramètres pour réessayer."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Touchez le capteur d\'empreintes digitales"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Appuyez sur l\'icône Déverrouiller pour continuer"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"Visage non reconnu. Utilisez l\'empreinte digitale."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"Visage non reconnu"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Utiliser l\'empreinte digitale"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"Déverrouillage par reconnaissance faciale inaccessible."</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth connecté"</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Recharge en cours… • Se terminera dans <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Balayer l\'écran vers la gauche pour démarrer le tutoriel communautaire"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Ouvrir l\'éditeur de widget"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personnaliser"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Fermer"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Ajouter, retirer et réorganiser vos widgets dans cet espace"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Ajouter plus de widgets"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Maintenez le doigt pour personnaliser les widgets"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"Retirer"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Ajouter un widget"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Terminé"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"Activer Bluetooth?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"Pour connecter votre clavier à votre tablette, vous devez d\'abord activer la connectivité Bluetooth."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Activer"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Réglages avancés des notifications"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Activé : en fonction du visage"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"Avec les réglages avancés des notifications, vous pouvez définir un degré d\'importance de 0 à 5 pour les notifications d\'une application. \n\n"<b>"Niveau 5"</b>" \n- Afficher dans le haut de la liste des notifications \n- Autoriser les interruptions en mode plein écran \n- Toujours afficher les aperçus \n\n"<b>"Niveau 4"</b>" \n- Empêcher les interruptions en mode plein écran \n- Toujours afficher les aperçus \n\n"<b>"Niveau 3"</b>" \n- Empêcher les interruptions en mode plein écran \n- Ne jamais afficher les aperçus \n\n"<b>"Niveau 2"</b>" \n- Empêcher les interruptions en mode plein écran \n- Ne jamais afficher les aperçus \n- Ne pas autoriser les sons et les vibrations \n\n"<b>"Niveau 1"</b>" \n- Empêcher les interruptions en mode plein écran \n- Ne jamais afficher les aperçus \n- Ne pas autoriser les sons et les vibrations \n- Masquer de l\'écran de verrouillage et de la barre d\'état status bar \n- Afficher dans le bas de la liste des notifications \n\n"<b>"Level 0"</b>" \n- Bloquer toutes les notifications de l\'application"</string> <string name="inline_done_button" msgid="6043094985588909584">"Terminé"</string> <string name="inline_ok_button" msgid="603075490581280343">"Appliquer"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Désactiver les notifications"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"Configuration"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"Stockage"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"Conseils"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"Accessibilité"</string> <string name="instant_apps" msgid="8337185853050247304">"Applications instantanées"</string> <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> en cours d\'exécution"</string> <string name="instant_apps_message" msgid="6112428971833011754">"Application ouverte sans avoir été installée."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Touchez pour ouvrir fonction. d\'access. Personnalisez ou remplacez bouton dans Param.\n\n"<annotation id="link">"Afficher param."</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Déplacez le bouton vers le bord pour le masquer temporairement"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Annuler"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"Bouton d\'accessibilité masqué"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Touchez pour afficher le bouton d\'accessibilité"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Le raccourci <xliff:g id="FEATURE_NAME">%s</xliff:g> a été retiré"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# raccourci retiré}one{# raccourci retiré}many{# de raccourcis retirés}other{# raccourcis retirés}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Déplacer dans coin sup. gauche"</string> diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml index 0c8ef28ed444..13af9a51c1f8 100644 --- a/packages/SystemUI/res/values-fr/strings.xml +++ b/packages/SystemUI/res/values-fr/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Impossible de configurer le déverrouillage par reconnaissance faciale. Accédez aux paramètres pour réessayer."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Appuyez sur le lecteur d\'empreinte digitale"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Appuyez sur l\'icône de déverrouillage pour continuer"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"Visage non reconnu. Utilisez votre empreinte."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"Visage non reconnu"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Utilisez empreinte digit."</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"Déverrouillage par reconnaissance faciale indisponible"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth connecté"</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Recharge • Temps restant : <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Balayer vers la gauche pour démarrer le tutoriel collectif"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Ouvrir l\'éditeur de widgets"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personnaliser"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Fermer"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Dans cet espace, ajoutez, supprimez et réorganisez vos widgets"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Ajouter des widgets"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Appuyez de manière prolongée pour personnaliser les widgets"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"Supprimer"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Ajouter un widget"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"OK"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"Activer le Bluetooth ?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"Pour connecter un clavier à votre tablette, vous devez avoir activé le Bluetooth."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Activer"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Commandes de gestion des notifications"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Active - En fonction du visage"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"Grâce aux commandes de gestion des notifications, vous pouvez définir le niveau d\'importance (compris entre 0 et 5) des notifications d\'une application. \n\n"<b>"Niveau 5"</b>" \n- Afficher en haut de la liste des notifications \n- Autoriser l\'interruption en plein écran \n- Toujours en aperçu \n\n"<b>"Niveau 4"</b>" \n- Empêcher l\'interruption en plein écran \n- Toujours en aperçu \n\n"<b>"Niveau 3"</b>" \n- Empêcher l\'interruption en plein écran \n- Jamais en aperçu \n\n"<b>"Niveau 2"</b>" \n- Empêcher l\'interruption en plein écran \n- Jamais en aperçu \n- Ne jamais émettre de signal sonore ni déclencher le vibreur \n\n"<b>"Niveau 1"</b>" \n- Empêcher l\'interruption en plein écran \n- Jamais en aperçu \n- Ne jamais émettre de signal sonore ni déclencher le vibreur \n- Masquer les notifications dans l\'écran de verrouillage et la barre d\'état \n- Afficher au bas de la liste des notifications \n\n"<b>"Niveau 0"</b>" \n- Bloquer toutes les notifications de l\'application"</string> <string name="inline_done_button" msgid="6043094985588909584">"OK"</string> <string name="inline_ok_button" msgid="603075490581280343">"Appliquer"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Désactiver les notifications"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"Configurer"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"Espace de stockage"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"Astuces"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"Accessibilité"</string> <string name="instant_apps" msgid="8337185853050247304">"Applis instantanées"</string> <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> en cours d\'exécution"</string> <string name="instant_apps_message" msgid="6112428971833011754">"Vous pouvez ouvrir cette application sans l\'installer."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Appuyez pour ouvrir fonctionnalités d\'accessibilité. Personnalisez ou remplacez bouton dans paramètres.\n\n"<annotation id="link">"Voir paramètres"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Déplacer le bouton vers le bord pour le masquer temporairement"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Annuler"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"Bouton Accessibilité masqué"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Appuyez pour afficher le bouton Accessibilité"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Raccourci vers <xliff:g id="FEATURE_NAME">%s</xliff:g> supprimé"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# raccourci supprimé}one{# raccourci supprimé}many{# raccourcis supprimés}other{# raccourcis supprimés}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Déplacer en haut à gauche"</string> diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml index a705f2aec70e..d30770d08e26 100644 --- a/packages/SystemUI/res/values-gl/strings.xml +++ b/packages/SystemUI/res/values-gl/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Non se puido configurar o desbloqueo facial. Para tentalo de novo, vai a Configuración."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Toca o sensor de impresión dixital"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Preme a icona de desbloquear para continuar"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"Non se recoñeceu a cara. Usa a impresión dixital."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"Non se recoñeceu a cara"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Usa a impresión dixital"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"O desbloqueo facial non está dispoñible"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth conectado"</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Cargando • A carga completarase en <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Pasa o dedo cara á esquerda para iniciar o titorial comunitario"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Abrir o editor de widgets"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personalizar"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Pechar"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Engadir, quitar e reordenar widgets neste espazo"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Engadir máis widgets"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Pulsación longa para personalizar os widgets"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"Quitar"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Engadir widget"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Feito"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"Queres activar o Bluetooth?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"Para conectar o teu teclado coa tableta, primeiro tes que activar o Bluetooth."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Activar"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Controis de notificacións mellorados"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Activada: baseada na cara"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"Cos controis de notificacións mellorados, podes asignarlles un nivel de importancia comprendido entre 0 e 5 ás notificacións dunha aplicación determinada. \n\n"<b>"Nivel 5"</b>" \n- Mostrar na parte superior da lista de notificacións. \n- Permitir interrupcións no modo de pantalla completa. \n- Mostrar sempre. \n\n"<b>"Nivel 4"</b>" \n- Impedir interrupcións no modo de pantalla completa. \n- Mostrar sempre. \n\n"<b>"Nivel 3"</b>" \n- Impedir interrupcións no modo de pantalla completa. \n- Non mostrar nunca. \n\n"<b>"Nivel 2"</b>" \n- Impedir interrupcións no modo de pantalla completa. \n- Non mostrar nunca. \n- Non soar nin vibrar nunca. \n\n"<b>"Nivel 1"</b>" \n- Impedir interrupcións no modo de pantalla completa. \n- Non mostrar nunca. \n- Non soar nin vibrar nunca. \n- Ocultar na pantalla de bloqueo e na barra de estado. \n- Mostrar na parte inferior da lista de notificacións. \n\n"<b>"Nivel 0"</b>" \n- Bloquear todas as notificacións da aplicación."</string> <string name="inline_done_button" msgid="6043094985588909584">"Feito"</string> <string name="inline_ok_button" msgid="603075490581280343">"Aplicar"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Desactivar notificacións"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"Configurar"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"Almacenamento"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"Consellos"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"Accesibilidade"</string> <string name="instant_apps" msgid="8337185853050247304">"Aplicacións Instantáneas"</string> <string name="instant_apps_title" msgid="8942706782103036910">"Estase executando <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="instant_apps_message" msgid="6112428971833011754">"Abriuse a aplicación sen ter que instalala."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Toca para abrir as funcións de accesibilidade. Cambia este botón en Configuración.\n\n"<annotation id="link">"Ver configuración"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Para ocultar temporalmente o botón, móveo ata o bordo"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Desfacer"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"O botón Accesibilidade está oculto"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Toca para mostrar o botón Accesibilidade"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Quitouse o atallo de <xliff:g id="FEATURE_NAME">%s</xliff:g>"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{Quitouse # atallo}other{Quitáronse # atallos}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Mover á parte super. esquerda"</string> diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml index 9965f450c565..62ffdd3c93a6 100644 --- a/packages/SystemUI/res/values-gu/strings.xml +++ b/packages/SystemUI/res/values-gu/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"ફેસ અનલૉક સુવિધાનું સેટઅપ કરી શક્યા નથી. ફરી પ્રયાસ કરવા માટે સેટિંગ પર જાઓ."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"ફિંગરપ્રિન્ટના સેન્સરને સ્પર્શ કરો"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"ચાલુ રાખવા \'અનલૉક કરો\' આઇકન દબાવો"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"ચહેરો ઓળખાયો નથી. તેને બદલે ફિંગરપ્રિન્ટ વાપરો."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"ચહેરો ઓળખાયો નથી"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"તો ફિંગરપ્રિન્ટ વાપરો"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"ફેસ અનલૉક સુવિધા ઉપલબ્ધ નથી"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"બ્લૂટૂથ કનેક્ટ થયું."</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ચાર્જ થઈ રહ્યું છે • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>માં પૂરું ચાર્જ થઈ જશે"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"કૉમ્યુનલ ટ્યૂટૉરિઅલ શરૂ કરવા માટે ડાબે સ્વાઇપ કરો"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"વિજેટ એડિટર ખોલો"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"કસ્ટમાઇઝ કરો"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"છોડી દો"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"આ સ્પેસમાં તમારા વિજેટ ઉમેરો, તેને કાઢી નાખો અને ફરી તેને ક્રમમાં ગોઠવો"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"વધુ વિજેટ ઉમેરો"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"વિજેટ કસ્ટમાઇઝ કરવા માટે થોડીવાર દબાવી રાખો"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"કાઢી નાખો"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"વિજેટ ઉમેરો"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"થઈ ગયું"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"બ્લૂટૂથ ચાલુ કરવુ છે?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"તમારા ટેબ્લેટ સાથે કીબોર્ડ કનેક્ટ કરવા માટે, તમારે પહેલાં બ્લૂટૂથ ચાલુ કરવાની જરૂર પડશે."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"ચાલુ કરો"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"પાવર સૂચના નિયંત્રણો"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"ચાલુ છે - ચહેરા આધારિત રોટેશન"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"પાવર સૂચના નિયંત્રણો સાથે, તમે ઍપની સૂચનાઓ માટે 0 થી 5 સુધીના મહત્વના સ્તરને સેટ કરી શકો છો. \n\n"<b>"સ્તર 5"</b>" \n- સૂચના સૂચિની ટોચ પર બતાવો \n- પૂર્ણ સ્ક્રીન અવરોધની મંજૂરી આપો \n- હંમેશાં ત્વરિત દૃષ્ટિ કરો \n\n"<b>"સ્તર 4"</b>" \n- પૂર્ણ સ્ક્રીન અવરોધ અટકાવો \n- હંમેશાં ત્વરિત દૃષ્ટિ કરો \n\n"<b>"સ્તર 3"</b>" \n- પૂર્ણ સ્ક્રીન અવરોધ અટકાવો \n- ક્યારેય ત્વરિત દૃષ્ટિ કરશો નહીં \n\n"<b>"સ્તર 2"</b>" \n- પૂર્ણ સ્ક્રીન અવરોધ અટકાવો \n- ક્યારેય ત્વરિત દૃષ્ટિ કરશો નહીં \n- ક્યારેય અવાજ અથવા વાઇબ્રેટ કરશો નહીં \n\n"<b>"સ્તર 1"</b>" \n- પૂર્ણ સ્ક્રીન અવરોધની મંજૂરી આપો \n- ક્યારેય ત્વરિત દૃષ્ટિ કરશો નહીં \n- ક્યારેય અવાજ અથવા વાઇબ્રેટ કરશો નહીં \n- લૉક સ્ક્રીન અને સ્ટેટસ બારથી છુપાવો \n- સૂચના સૂચિના તળિયા પર બતાવો \n\n"<b>"સ્તર 0"</b>" \n- ઍપની તમામ સૂચનાઓને બ્લૉક કરો"</string> <string name="inline_done_button" msgid="6043094985588909584">"થઈ ગયું"</string> <string name="inline_ok_button" msgid="603075490581280343">"લાગુ કરો"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"નોટિફિકેશન બંધ કરો"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"સેટઅપ કરો"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"સ્ટોરેજ"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"હિન્ટ"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"ઍક્સેસિબિલિટી"</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> ચાલી રહી છે"</string> <string name="instant_apps_message" msgid="6112428971833011754">"ઍપ ઇન્સ્ટૉલ કર્યા વિના ખુલી જાય છે."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"ઍક્સેસિબિલિટી સુવિધાઓ ખોલવા માટે ટૅપ કરો. સેટિંગમાં આ બટનને કસ્ટમાઇઝ કરો અથવા બદલો.\n\n"<annotation id="link">"સેટિંગ જુઓ"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"તેને હંગામી રૂપે ખસેડવા માટે બટનને કિનારી પર ખસેડો"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"છેલ્લો ફેરફાર રદ કરો"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"ઍક્સેસિબિલિટી બટન છુપાવેલું છે"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"ઍક્સેસિબિલિટી બટન બતાવવા માટે ટૅપ કરો"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> શૉર્ટકટ કાઢી નાખ્યો"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# શૉર્ટકટ કાઢી નાખ્યો}one{# શૉર્ટકટ કાઢી નાખ્યો}other{# શૉર્ટકટ કાઢી નાખ્યા}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"ઉપર ડાબે ખસેડો"</string> diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml index e2ed3abb92cd..65cf5f790544 100644 --- a/packages/SystemUI/res/values-hi/strings.xml +++ b/packages/SystemUI/res/values-hi/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"फ़ेस अनलॉक की सुविधा सेट अप नहीं की जा सकी. सेटिंग पर जाकर दोबारा कोशिश करें."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"फ़िंगरप्रिंट सेंसर को छुएं"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"जारी रखने के लिए अनलॉक आइकॉन पर टैप करें"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"चेहरा नहीं पहचाना गया. फ़िंगरप्रिंट इस्तेमाल करें."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"चेहरा नहीं पहचाना गया"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"फ़िंगरप्रिंट इस्तेमाल करें"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"फ़ेस अनलॉक की सुविधा उपलब्ध नहीं है"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"ब्लूटूथ कनेक्ट किया गया."</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • चार्ज हो रहा है • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> में पूरा चार्ज हो जाएगा"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"कम्यूनिटी ट्यूटोरियल शुरू करने के लिए, बाईं ओर स्वाइप करें"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"विजेट एडिटर खोलें"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"पसंद के मुताबिक बनाएं"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"खारिज करें"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"इस स्पेस में विजेट जोड़ें, हटाएं, और उन्हें फिर से क्रम में लगाएं"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"ज़्यादा विजेट जोड़ें"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"विजेट पसंद के मुताबिक बनाने के लिए उसे दबाकर रखें"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"हटाएं"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"विजेट जोड़ें"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"हो गया"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"ब्लूटूथ चालू करें?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"अपने कीबोर्ड को अपने टैबलेट से कनेक्ट करने के लिए, आपको पहले ब्लूटूथ चालू करना होगा."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"चालू करें"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"पावर सूचना नियंत्रण"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"चालू है - चेहरे की गतिविधि के हिसाब से कैमरे को घुमाने की सुविधा"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"पावर सूचना नियंत्रण के ज़रिये, आप किसी ऐप की सूचना को उसकी अहमियत के हिसाब से 0 से 5 के लेवल पर सेट कर सकते हैं.\n\n"<b>"लेवल 5"</b>" \n- सूचना सूची में सबसे ऊपर दिखाएं \n- पूरे स्क्रीन को ढंकने की अनुमति दें \n- लगातार देखते रहें \n\n"<b>" लेवल 4"</b>" \n- पूरे स्क्रीन को ढंकें \n- लगातार देखते रहें \n\n"<b>"लेवल 3"</b>" \n- पूरे स्क्रीन को ढंकने से रोकें \n-कभी भी न देखें \n\n"<b>"लेवल 2"</b>" \n- पूरे स्क्रीन को ढंकने से रोकें \n- कभी भी देखें \n- कभी भी आवाज़ या कंपन (वाइब्रेशन) न करें \n\n"<b>"लेवल 1"</b>" \n- पूरे स्क्रीन को ढंकने से रोकें \n- कभी भी न देखें \n- कभी भी आवाज़ या कंपन (वाइब्रेशन) न करें \n- लॉक स्क्रीन और स्टेटस बार से छिपाएं \n- सूचना सूची के नीचे दिखाएं \n\n"<b>"लेवल 0"</b>" \n- ऐप्लिकेशन की सभी सूचनाएं रोक दें"</string> <string name="inline_done_button" msgid="6043094985588909584">"हो गया"</string> <string name="inline_ok_button" msgid="603075490581280343">"लागू करें"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"सूचनाएं बंद करें"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"सेट अप"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"स्टोरेज"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"संकेत"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"सुलभता"</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> चल रहा है"</string> <string name="instant_apps_message" msgid="6112428971833011754">"ऐप्लिकेशन इंस्टॉल किए बिना ही खुल गया है."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"सुलभता सुविधाएं खोलने के लिए टैप करें. सेटिंग में, इस बटन को बदलें या अपने हिसाब से सेट करें.\n\n"<annotation id="link">"सेटिंग देखें"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"बटन को कुछ समय छिपाने के लिए, उसे किनारे पर ले जाएं"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"पहले जैसा करें"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"सुलभता बटन छिपा है"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"सुलभता बटन दिखाने के लिए टैप करें"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> का शॉर्टकट हटाया गया"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# शॉर्टकट हटाया गया}one{# शॉर्टकट हटाया गया}other{# शॉर्टकट हटाए गए}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"सबसे ऊपर बाईं ओर ले जाएं"</string> diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml index f5d73eadf3da..b502e85c1873 100644 --- a/packages/SystemUI/res/values-hr/strings.xml +++ b/packages/SystemUI/res/values-hr/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Postavljanje otključavanja licem nije uspjelo. Pokušajte ponovo u postavkama."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Dodirnite senzor otiska prsta"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Pritisnite ikonu otključavanja da biste nastavili"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"Lice nije prepoznato. Upotrijebite otisak prsta."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"Lice nije prepoznato"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Upotrijebite otisak prsta"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"Otključavanje licem nije dostupno"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth povezan."</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • punjenje • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> do napunjenosti"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Prijeđite prstom ulijevo da biste pokrenuli zajednički vodič"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Otvaranje alata za uređivanje widgeta"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Prilagodi"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Odbaci"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Dodavanje, uklanjanje i promjena redoslijeda widgeta u ovom prostoru"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Dodavanje još widgeta"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Dugo pritisnite za prilagodbu widgeta"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"Ukloni"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Dodaj widget"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Gotovo"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"Želite li uključiti Bluetooth?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"Da biste povezali tipkovnicu s tabletom, morate uključiti Bluetooth."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Uključi"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Napredne kontrole obavijesti"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Uključeno – na temelju lica"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"Napredne kontrole obavijesti omogućuju vam da postavite razinu važnosti za obavijesti aplikacije od 0 do 5. \n\n"<b>"Razina 5"</b>" \n– prikaži na vrhu popisa obavijesti \n– dopusti prekide prikaza na cijelom zaslonu \n– uvijek dopusti brzi pregled \n\n"<b>"Razina 4"</b>" \n– onemogući prekid prikaza na cijelom zaslonu \n– uvijek dopusti brzi pregled \n\n"<b>"Razina 3"</b>" \n– onemogući prekid prikaza na cijelom zaslonu \n– nikad ne dopusti brzi pregled\n\n"<b>"Razina 2"</b>" \n– onemogući prekid prikaza na cijelom zaslonu \n– nikad ne dopusti brzi pregled \n– nikad ne emitiraj zvuk ni vibraciju \n\n"<b>"Razina 1"</b>" \n– onemogući prekid prikaza na cijelom zaslonu \n– nikad ne dopusti brzi pregled \n– nikad ne emitiraj zvuk ni vibraciju \n– ne prikazuj na zaključanom zaslonu i traci statusa \n– prikaži na dnu popisa obavijesti \n\n"<b>"Razina 0"</b>" \n– blokiraj sve obavijesti aplikacije"</string> <string name="inline_done_button" msgid="6043094985588909584">"Gotovo"</string> <string name="inline_ok_button" msgid="603075490581280343">"Primijeni"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Isključi obavijesti"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"Postavljanje"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"Pohrana"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"Savjeti"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"Pristupačnost"</string> <string name="instant_apps" msgid="8337185853050247304">"Instant aplikacije"</string> <string name="instant_apps_title" msgid="8942706782103036910">"Izvodi se aplikacija <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="instant_apps_message" msgid="6112428971833011754">"Aplikacija je otvorena bez instaliranja."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Dodirnite za otvaranje značajki pristupačnosti. Prilagodite ili zamijenite taj gumb u postavkama.\n\n"<annotation id="link">"Pregledajte postavke"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Pomaknite gumb do ruba da biste ga privremeno sakrili"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Poništi"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"Gumb za pristupačnost je skriven"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Dodirnite za prikaz gumba za pristupačnost"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Uklonjen je prečac za uslugu <xliff:g id="FEATURE_NAME">%s</xliff:g>"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{Uklonjen je # prečac}one{Uklonjen je # prečac}few{Uklonjena su # prečaca}other{Uklonjeno je # prečaca}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Premjesti u gornji lijevi kut"</string> @@ -1225,7 +1213,7 @@ <string name="assistant_attention_content_description" msgid="4166330881435263596">"Otkrivena je prisutnost korisnika"</string> <string name="set_default_notes_app_toast_content" msgid="2812374329662610753">"Postavite zadanu aplikaciju za bilješke u postavkama"</string> <string name="install_app" msgid="5066668100199613936">"Instalacija"</string> - <string name="dismissible_keyguard_swipe" msgid="2213369651289613196">"Prijeđite prstom da biste nastavili"</string> + <string name="dismissible_keyguard_swipe" msgid="2213369651289613196">"Prijeđite prstom za nastavak"</string> <string name="connected_display_dialog_start_mirroring" msgid="6237895789920854982">"Želite li zrcaliti na vanjski zaslon?"</string> <string name="connected_display_dialog_dual_display_stop_warning" msgid="4174707498892447947">"Unutarnji zaslon bit će zrcaljen. Prednji zaslon bit će isključen."</string> <string name="mirror_display" msgid="2515262008898122928">"Zrcaljenje zaslona"</string> diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml index 9ac44dfd7972..c7ce0b5b4821 100644 --- a/packages/SystemUI/res/values-hu/strings.xml +++ b/packages/SystemUI/res/values-hu/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Nem sikerült beállítani az arcalapú feloldást. Próbálkozzon újra a Beállításokban."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Érintse meg az ujjlenyomat-érzékelőt"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"A folytatáshoz koppintson a Feloldás ikonra"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"Sikertelen arcfelismerés. Használjon ujjlenyomatot."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"Sikertelen arcfelismerés"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Használjon ujjlenyomatot"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"Nem áll rendelkezésre az Arcalapú feloldás"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth csatlakoztatva."</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Töltés • A teljes töltöttségig: <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Csúsztasson gyorsan balra a közösségi útmutató elindításához"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"A modulszerkesztő megnyitása"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Személyre szabás"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Elvetés"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Modulok hozzáadása, eltávolítása és átrendezése ezen a területen"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"További modulok hozzáadása"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Nyomja meg hosszan a modulok személyre szabásához"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"Eltávolítás"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Modul hozzáadása"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Kész"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"Engedélyezi a Bluetooth-kapcsolatot?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"Ha a billentyűzetet csatlakoztatni szeretné táblagépéhez, először engedélyeznie kell a Bluetooth-kapcsolatot."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Bekapcsolás"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Teljes körű értesítésvezérlők"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Be: Arcalapú"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"Az értesítési beállítások révén 0-tól 5-ig állíthatja be a fontossági szintet az alkalmazás értesítéseinél. \n\n"<b>"5. szint"</b>" \n– Megjelenítés az értesítési lista tetején \n– Teljes képernyő megszakításának engedélyezése \n– Mindig felugrik \n\n"<b>"4. szint"</b>" \n– Teljes képernyő megszakításának megakadályozása \n– Mindig felugrik \n\n"<b>"3. szint"</b>" \n– Teljes képernyő megszakításának megakadályozása \n– Soha nem ugrik fel \n\n"<b>"2. szint"</b>" \n– Teljes képernyő megszakításának megakadályozása \n– Soha nem ugrik fel \n– Soha nincs hangjelzés és rezgés \n\n"<b>"1. szint"</b>" \n– Teljes képernyő megszakításának megakadályozása \n– Soha nem ugrik fel \n– Soha nincs hangjelzés vagy rezgés \n– Elrejtés a lezárási képernyőről és az állapotsávról \n– Megjelenítés az értesítési lista alján \n\n"<b>"0. szint"</b>" \n– Az alkalmazás összes értesítésének letiltása"</string> <string name="inline_done_button" msgid="6043094985588909584">"Kész"</string> <string name="inline_ok_button" msgid="603075490581280343">"Alkalmaz"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Az értesítések kikapcsolása"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"Beállítás"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"Tárhely"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"Tippek"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"Kisegítő lehetőségek"</string> <string name="instant_apps" msgid="8337185853050247304">"Azonnali alkalmazások"</string> <string name="instant_apps_title" msgid="8942706782103036910">"A(z) <xliff:g id="APP">%1$s</xliff:g> alkalmazás jelenleg fut"</string> <string name="instant_apps_message" msgid="6112428971833011754">"Az alkalmazás telepítés nélkül lett megnyitva."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Koppintson a kisegítő lehetőségek megnyitásához. A gombot a Beállításokban módosíthatja.\n\n"<annotation id="link">"Beállítások"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"A gombot a szélre áthelyezve ideiglenesen elrejtheti"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Visszavonás"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"Kisegítő lehetőségek gomb elrejtve"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Koppintson a Kisegítő lehetőségek gomb megjelenítéséhez"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> gyorsparancs eltávolítva"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# gyorsparancs eltávolítva}other{# gyorsparancs eltávolítva}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Áthelyezés fel és balra"</string> diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml index 0d59017df9e5..7db84dbc4c92 100644 --- a/packages/SystemUI/res/values-hy/strings.xml +++ b/packages/SystemUI/res/values-hy/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Չհաջողվեց կարգավորել դեմքով ապակողպումը։ Անցեք Կարգավորումներ և նորից փորձեք։"</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Հպեք մատնահետքի սկաներին"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Շարունակելու համար սեղմեք ապակողպման պատկերակը"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"Դեմքը չի ճանաչվել։ Օգտագործեք մատնահետքը։"</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"Դեմքը չի ճանաչվել"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Օգտագործեք մատնահետք"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"Դեմքով ապակողպումն անհասանելի է"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth-ը միացված է:"</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Լիցքավորում • Մնացել է <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Թերթեք ձախ՝ ուղեցույցը գործարկելու համար"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Բացել վիջեթների խմբագրիչը"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Անհատականացնել"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Փակել"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Ավելացնել վիջեթներ, ինչպես նաև հեռացնել և վերադասավորել դրանք այս տարածքում"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Ավելացնել վիջեթներ"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Երկար սեղմեք՝ վիջեթները հարմարեցնելու համար"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"Հեռացնել"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Ավելացնել վիջեթ"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Պատրաստ է"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"Միացնե՞լ Bluetooth-ը:"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"Ստեղնաշարը ձեր պլանշետին միացնելու համար նախ անհրաժեշտ է միացնել Bluetooth-ը:"</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Միացնել"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Ծանուցումների ընդլայնված կառավարում"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Միաց․ – Դիմաճանաչման հիման վրա"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"Ծանուցումների ընդլայնված կառավարման օգնությամբ կարող եք յուրաքանչյուր հավելվածի ծանուցումների համար նշանակել կարևորության աստիճան՝ 0-5 սահմաններում: \n\n"<b>"5-րդ աստիճան"</b>" \n- Ցուցադրել ծանուցումների ցանկի վերևում \n- Թույլատրել լիաէկրան ընդհատումները \n- Միշտ ցուցադրել կարճ ծանուցումները \n\n"<b>"4-րդ աստիճան"</b>" \n- Արգելել լիաէկրան ընդհատումները \n- Միշտ ցուցադրել կարճ ծանուցումները \n\n"<b>"3-րդ աստիճան"</b>" \n- Արգելել լիաէկրան ընդհատումները \n- Արգելել կարճ ծանուցումների ցուցադրումը \n\n"<b>"2-րդ աստիճան"</b>" \n- Արգելել լիաէկրան ընդհատումները \n- Արգելել կարճ ծանուցումների ցուցադրումը \n- Անջատել ձայնը և թրթռումը \n\n"<b>"1-ին աստիճան"</b>" \n- Արգելել լիաէկրան ընդհատումները \n- Արգելել կարճ ծանուցումների ցուցադրումը \n- Անջատել ձայնը և թրթռումը \n- Չցուցադրել կողպէկրանում և կարգավիճակի գոտում \n- Ցուցադրել ծանուցումների ցանկի ներքևում \n\n"<b>"0-րդ աստիճան"</b>\n"- Արգելափակել հավելվածի բոլոր ծանուցումները"</string> <string name="inline_done_button" msgid="6043094985588909584">"Փակել"</string> <string name="inline_ok_button" msgid="603075490581280343">"Կիրառել"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Անջատել ծանուցումները"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"Կարգավորում"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"Տարածք"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"Հուշումներ"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"Հատուկ գործառույթներ"</string> <string name="instant_apps" msgid="8337185853050247304">"Ակնթարթային հավելվածներ"</string> <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> հավելվածն աշխատում է"</string> <string name="instant_apps_message" msgid="6112428971833011754">"Հավելվածը բացվել է առանց տեղադրման։"</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Հատուկ գործառույթները բացելու համար հպեք։ Անհատականացրեք այս կոճակը կարգավորումներում։\n\n"<annotation id="link">"Կարգավորումներ"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Կոճակը ժամանակավորապես թաքցնելու համար այն տեղափոխեք էկրանի եզր"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Հետարկել"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"«Հատուկ գործառույթներ» կոճակը թաքցված է"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Հպեք՝ «Հատուկ գործառույթներ» կոճակը ցուցադրելու համար"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"«<xliff:g id="FEATURE_NAME">%s</xliff:g>» դյուրանցումը հեռացվեց"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# դյուրանցում հեռացվեց}one{# դյուրանցում հեռացվեց}other{# դյուրանցում հեռացվեց}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Տեղափոխել վերև՝ ձախ"</string> diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml index a0b51992e22b..b7e7e8150e77 100644 --- a/packages/SystemUI/res/values-in/strings.xml +++ b/packages/SystemUI/res/values-in/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Tidak dapat menyiapkan buka dengan wajah. Buka Setelan untuk mencoba lagi."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Sentuh sensor sidik jari"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Tekan ikon buka kunci untuk melanjutkan"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"Wajah tidak dikenali. Gunakan sidik jari."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"Wajah tidak dikenali"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Gunakan sidik jari"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"Buka dengan Wajah tidak tersedia"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth terhubung."</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengisi daya • Penuh dalam waktu <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Geser ke kiri untuk memulai tutorial komunal"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Buka editor widget"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Sesuaikan"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Tutup"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Tambahkan, hapus, dan susun ulang widget Anda di ruang ini"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Tambahkan widget lainnya"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Tekan lama untuk menyesuaikan widget"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"Hapus"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Tambahkan widget"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Selesai"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"Aktifkan Bluetooth?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"Untuk menghubungkan keyboard dengan tablet, terlebih dahulu aktifkan Bluetooth."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Aktifkan"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Kontrol notifikasi daya"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Aktif - Berbasis deteksi wajah"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"Dengan kontrol notifikasi daya, Anda dapt menyetel level kepentingan notifikasi aplikasi dari 0 sampai 5. \n\n"<b>"Level 5"</b>" \n- Muncul di atas daftar notifikasi \n- Izinkan interupsi layar penuh \n- Selalu intip pesan \n\n"<b>"Level 4"</b>" \n- Jangan interupsi layar penuh \n- Selalu intip pesan \n\n"<b>"Level 3"</b>" \n- Jangan interupsi layar penuh \n- Tak pernah intip pesan \n\n"<b>"Level 2"</b>" \n- Jangan interupsi layar penuh \n- Tak pernah intip pesan \n- Tanpa suara dan getaran \n\n"<b>"Level 1"</b>" \n- Jangan interupsi layar penuh \n- Tak pernah intip pesan \n- Tanpa suara atau getaran \n- Sembunyikan dari layar kunci dan bilah status \n- Muncul di bawah daftar notifikasi \n\n"<b>"Level 0"</b>" \n- Blokir semua notifikasi dari aplikasi"</string> <string name="inline_done_button" msgid="6043094985588909584">"Selesai"</string> <string name="inline_ok_button" msgid="603075490581280343">"Terapkan"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Nonaktifkan notifikasi"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"Penyiapan"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"Penyimpanan"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"Petunjuk"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"Aksesibilitas"</string> <string name="instant_apps" msgid="8337185853050247304">"Aplikasi Instan"</string> <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> sedang berjalan"</string> <string name="instant_apps_message" msgid="6112428971833011754">"Aplikasi dapat dibuka tanpa perlu diinstal."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Ketuk untuk membuka fitur aksesibilitas. Sesuaikan atau ganti tombol ini di Setelan.\n\n"<annotation id="link">"Lihat setelan"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Pindahkan tombol ke tepi agar tersembunyi untuk sementara"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Urungkan"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"Tombol aksesibilitas tersembunyi"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Ketuk untuk menampilkan tombol aksesibilitas"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Pintasan <xliff:g id="FEATURE_NAME">%s</xliff:g> dihapus"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# pintasan dihapus}other{# pintasan dihapus}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Pindahkan ke kiri atas"</string> diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml index 3a0843e4f720..db1b74392cd8 100644 --- a/packages/SystemUI/res/values-is/strings.xml +++ b/packages/SystemUI/res/values-is/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Ekki var hægt að setja upp andlitskenni. Farðu í stillingar og reyndu aftur."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Snertu fingrafaralesarann"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Ýttu á táknið taka úr lás til að halda áfram"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"Ekki tókst að bera kennsl á andlit. Notaðu fingrafar í staðinn."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"Ekki tókst að bera kennsl á andlit"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Nota fingrafar í staðinn"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"Andlitskenni ekki í boði"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth tengt."</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Í hleðslu • Full hleðsla eftir <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Strjúktu til vinstri til að hefja samfélagsleiðsögnina"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Opna græjuritilinn"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Sérsníða"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Hunsa"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Bættu við, fjarlægðu og endurraðaðu græjunum þínum í þessu rými"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Bæta við fleiri græjum"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Haltu inni til að sérsníða græjur"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"Fjarlægja"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Bæta græju við"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Lokið"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"Kveikja á Bluetooth?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"Til að geta tengt lyklaborðið við spjaldtölvuna þarftu fyrst að kveikja á Bluetooth."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Kveikja"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Orkustillingar tilkynninga"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Kveikt – út frá andliti"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"Með orkutilkynningastýringum geturðu stillt mikilvægi frá 0 upp í 5 fyrir tilkynningar forrita. \n\n"<b>"Stig 5"</b>" \n- Sýna efst á tilkynningalista \n- Leyfa truflun þegar birt er á öllum skjánum \n- Kíkja alltaf \n\n"<b>"Stig 4"</b>" \n- Hindra truflun við birtingu á öllum skjánum \n- Kíkja alltaf \n\n"<b>"Stig 3"</b>" \n- Hindra truflun við birtingu á öllum skjánum \n- Kíkja aldrei \n\n"<b>"Stig 2"</b>" \n- Hindra truflun við birtingu á öllum skjánum \n- Kíkja aldrei \n- Slökkva á hljóði og titringi \n\n"<b>"Stig 1"</b>" \n- Hindra truflun við birtingu á öllum skjánum \n- Kíkja aldrei \n- Slökkva á hljóði og titringi \n- Fela á lásskjá og stöðustiku \n- Sýna neðst á tilkynningalista \n\n"<b>"Stig 0"</b>" \n- Setja allar tilkynningar frá forriti á bannlista"</string> <string name="inline_done_button" msgid="6043094985588909584">"Lokið"</string> <string name="inline_ok_button" msgid="603075490581280343">"Nota"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Slökkva á tilkynningum"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"Uppsetning"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"Geymslurými"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"Vísbendingar"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"Aðgengileiki"</string> <string name="instant_apps" msgid="8337185853050247304">"Skyndiforrit"</string> <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> er í gangi"</string> <string name="instant_apps_message" msgid="6112428971833011754">"Forrit opnað án þess að vera uppsett."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Ýttu til að opna aðgengiseiginleika. Sérsníddu eða skiptu hnappinum út í stillingum.\n\n"<annotation id="link">"Skoða stillingar"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Færðu hnappinn að brúninni til að fela hann tímabundið"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Afturkalla"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"Aðgengishnappur falinn"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Ýttu til að sjá aðgengishnappinn"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Flýtileiðin <xliff:g id="FEATURE_NAME">%s</xliff:g> var fjarlægð"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# flýtileið var fjarlægð}one{# flýtileið var fjarlægð}other{# flýtileiðir voru fjarlægðar}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Færa efst til vinstri"</string> diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml index 8ee96fcd39fd..997b76b7ae3b 100644 --- a/packages/SystemUI/res/values-it/strings.xml +++ b/packages/SystemUI/res/values-it/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Impossibile configurare lo Sblocco con il Volto. Vai alle Impostazioni e riprova."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Tocca il sensore di impronte"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Premi l\'icona Sblocca per continuare"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"Volto non riconosciuto. Usa l\'impronta."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"Volto non riconosciuto"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Usa l\'impronta"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"Sblocco con il Volto non disponibile"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth collegato."</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • In carica • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> alla ricarica completa"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Scorri a sinistra per iniziare il tutorial della community"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Apri l\'editor del widget"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personalizza"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Chiudi"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Aggiungi, rimuovi e riordina i tuoi widget in questo spazio"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Aggiungi altri widget"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Premi a lungo per personalizzare i widget"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"Rimuovi"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Aggiungi widget"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Fine"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"Attivare il Bluetooth?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"Per connettere la tastiera al tablet, devi prima attivare il Bluetooth."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Attiva"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Controlli di gestione delle notifiche"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"On - Rotazione basata sul viso"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"I controlli di gestione delle notifiche ti consentono di impostare un livello di importanza compreso tra 0 e 5 per le notifiche di un\'app. \n\n"<b>"Livello 5"</b>" \n- Mostra in cima all\'elenco di notifiche \n- Consenti l\'interruzione a schermo intero \n- Visualizza sempre \n\n"<b>"Livello 4"</b>" \n- Impedisci l\'interruzione a schermo intero \n- Visualizza sempre \n\n"<b>"Livello 3"</b>" \n- Impedisci l\'interruzione a schermo intero \n- Non visualizzare mai \n\n"<b>"Livello 2"</b>" \n- Impedisci l\'interruzione a schermo intero \n- Non visualizzare mai \n- Non emettere mai suoni e vibrazioni \n\n"<b>"Livello 1"</b>" \n- Impedisci l\'interruzione a schermo intero \n- Non visualizzare mai \n- Non emettere mai suoni e vibrazioni \n- Nascondi da schermata di blocco e barra di stato \n- Mostra in fondo all\'elenco di notifiche \n\n"<b>"Livello 0"</b>" \n- Blocca tutte le notifiche dell\'app"</string> <string name="inline_done_button" msgid="6043094985588909584">"Fine"</string> <string name="inline_ok_button" msgid="603075490581280343">"Applica"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Disattiva notifiche"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"Configurazione"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"Spazio di archiviazione"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"Suggerimenti"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"Accessibilità"</string> <string name="instant_apps" msgid="8337185853050247304">"App istantanee"</string> <string name="instant_apps_title" msgid="8942706782103036910">"App <xliff:g id="APP">%1$s</xliff:g> in esecuzione"</string> <string name="instant_apps_message" msgid="6112428971833011754">"App aperta senza essere stata installata."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Tocca per aprire funzioni di accessibilità. Personalizza o sostituisci il pulsante in Impostazioni.\n\n"<annotation id="link">"Vedi impostazioni"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Sposta il pulsante fino al bordo per nasconderlo temporaneamente"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Elimina"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"Pulsante Accessibilità nascosto"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Tocca per mostrare il pulsante Accessibilità"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Scorciatoia <xliff:g id="FEATURE_NAME">%s</xliff:g> rimossa"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# scorciatoia rimossa}many{# scorciatoie rimosse}other{# scorciatoie rimosse}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Sposta in alto a sinistra"</string> diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml index 17236eacd722..22079ac98ee5 100644 --- a/packages/SystemUI/res/values-iw/strings.xml +++ b/packages/SystemUI/res/values-iw/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"לא ניתן להגדיר פתיחה ע\"י זיהוי הפנים. צריך לעבור להגדרות כדי לנסות שוב."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"יש לגעת בחיישן טביעות האצבע"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"להמשך יש ללחוץ על סמל ביטול הנעילה"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"הפנים לא זוהו. צריך להשתמש בטביעת אצבע במקום."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"הפנים לא זוהו"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"שימוש בטביעת אצבע במקום זאת"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"אי אפשר לפתוח בזיהוי פנים"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth מחובר."</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • בטעינה • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> עד לסיום"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"אפשר להחליק שמאלה כדי להפעיל את המדריך המשותף"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"פתיחה של הכלי לעריכת ווידג\'טים"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"התאמה אישית"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"סגירה"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"הוספה, הסרה, וסידור מחדש של הווידג\'טים במרחב הזה"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"הוספת ווידג\'טים"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"לוחצים לחיצה ארוכה כדי להתאים אישית את הווידג\'טים"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"הסרה"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"הוספת ווידג\'ט"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"סיום"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"האם להפעיל את ה-Bluetooth?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"כדי לחבר את המקלדת לטאבלט, תחילה עליך להפעיל את ה-Bluetooth."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"הפעלה"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"פקדים של הודעות הפעלה"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"פועל – מבוסס על זיהוי פנים"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"בעזרת פקדים של התראות הפעלה, אפשר להגדיר רמת חשיבות מ-0 עד 5 להתראות אפליקציה. \n\n"<b>"רמה 5"</b>" \n- הצגה בראש רשימת ההתראות \n- לאפשר הפרעה במסך מלא \n- תמיד לאפשר הצצה \n\n"<b>"רמה 4"</b>" \n- מניעת הפרעה במסך מלא \n- תמיד לאפשר הצצה \n\n"<b>"רמה 3"</b>" \n- מניעת הפרעה במסך מלא \n- אף פעם לא לאפשר הצצה \n\n"<b>"רמה 2"</b>" \n- מניעת הפרעה במסך מלא \n- אף פעם לא לאפשר הצצה \n- אף פעם לא לאפשר קול ורטט \n\n"<b>"רמה 1"</b>" \n- מניעת הפרעה במסך מלא \n- אף פעם לא לאפשר הצצה \n- אף פעם לא לאפשר קול ורטט \n- הסתרה ממסך הנעילה ומשורת הסטטוס \n- הצגה בתחתית רשימת ההתראות \n\n"<b>"רמה 0"</b>" \n- חסימת כל ההתראות מהאפליקציה"</string> <string name="inline_done_button" msgid="6043094985588909584">"סיום"</string> <string name="inline_ok_button" msgid="603075490581280343">"אישור"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"השבתת ההתראות"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"הגדרה"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"אחסון"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"טיפים"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"נגישות"</string> <string name="instant_apps" msgid="8337185853050247304">"אפליקציות ללא התקנה"</string> <string name="instant_apps_title" msgid="8942706782103036910">"האפליקציה <xliff:g id="APP">%1$s</xliff:g> פועלת"</string> <string name="instant_apps_message" msgid="6112428971833011754">"האפליקציה נפתחת בלי התקנה."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"מקישים כדי לפתוח את תכונות הנגישות. אפשר להחליף את הלחצן או להתאים אותו אישית בהגדרות.\n\n"<annotation id="link">"הצגת ההגדרות"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"כדי להסתיר זמנית את הלחצן, יש להזיז אותו לקצה"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"ביטול"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"לחצן הנגישות מוסתר"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"אפשר להקיש כדי לראות את לחצן הנגישות"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"קיצור הדרך אל <xliff:g id="FEATURE_NAME">%s</xliff:g> הוסר"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{קיצור הדרך הוסר}one{# קיצורי דרך הוסרו}two{# קיצורי דרך הוסרו}other{# קיצורי דרך הוסרו}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"העברה לפינה השמאלית העליונה"</string> @@ -957,7 +945,7 @@ <string name="accessibility_floating_button_action_move_out_edge_and_show" msgid="8354760891651663326">"העברה מהשוליים והצגה"</string> <string name="accessibility_floating_button_action_remove_menu" msgid="6730432848162552135">"הסרה"</string> <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"החלפת מצב"</string> - <string name="quick_controls_title" msgid="6839108006171302273">"לחצני מכשירים"</string> + <string name="quick_controls_title" msgid="6839108006171302273">"ממשק השליטה במכשירים"</string> <string name="controls_providers_title" msgid="6879775889857085056">"יש לבחור אפליקציה כדי להוסיף פקדים"</string> <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{נוסף אמצעי בקרה אחד (#).}one{נוספו # אמצעי בקרה.}two{נוספו # אמצעי בקרה.}other{נוספו # אמצעי בקרה.}}"</string> <string name="controls_removed" msgid="3731789252222856959">"הוסר"</string> @@ -971,7 +959,7 @@ <string name="accessibility_control_change_unfavorite" msgid="6997408061750740327">"להסיר מהמועדפים"</string> <string name="accessibility_control_move" msgid="8980344493796647792">"העברה למיקום <xliff:g id="NUMBER">%d</xliff:g>"</string> <string name="controls_favorite_default_title" msgid="967742178688938137">"פקדים"</string> - <string name="controls_favorite_subtitle" msgid="5818709315630850796">"יש לבחור פקדי מכשירים כדי לקבל גישה מהירה"</string> + <string name="controls_favorite_subtitle" msgid="5818709315630850796">"יש לבחור מכשירים כדי לגשת אליהם במהירות מממשק השליטה במכשירים"</string> <string name="controls_favorite_rearrange" msgid="5616952398043063519">"כדי לארגן מחדש את הפקדים, צריך ללחוץ לחיצה ארוכה ולגרור"</string> <string name="controls_favorite_removed" msgid="5276978408529217272">"כל הפקדים הוסרו"</string> <string name="controls_favorite_toast_no_changes" msgid="7094494210840877931">"השינויים לא נשמרו"</string> @@ -982,7 +970,7 @@ <string name="controls_favorite_load_error" msgid="5126216176144877419">"לא ניתן היה לטעון את הפקדים. יש לבדוק את האפליקציה <xliff:g id="APP">%s</xliff:g> כדי לוודא שהגדרות האפליקציה לא השתנו."</string> <string name="controls_favorite_load_none" msgid="7687593026725357775">"פקדים תואמים לא זמינים"</string> <string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"אחר"</string> - <string name="controls_dialog_title" msgid="2343565267424406202">"הוספה לפקדי המכשירים"</string> + <string name="controls_dialog_title" msgid="2343565267424406202">"הוספה לממשק השליטה במכשירים"</string> <string name="controls_dialog_ok" msgid="2770230012857881822">"הוספה"</string> <string name="controls_dialog_remove" msgid="3775288002711561936">"הסרה"</string> <string name="controls_dialog_message" msgid="342066938390663844">"הוצע על-ידי <xliff:g id="APP">%s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml index e193cb14b577..74ccd50daad7 100644 --- a/packages/SystemUI/res/values-ja/strings.xml +++ b/packages/SystemUI/res/values-ja/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"顔認証を設定できませんでした。[設定] に移動してもう一度お試しください。"</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"指紋認証センサーをタッチ"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"ロック解除アイコンを押して続行してください"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"顔を認識できません。指紋認証を使用してください。"</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"顔を認識できません"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"指紋認証をお使いください"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"顔認証を利用できません"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetoothに接続済み。"</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 充電中 • フル充電まで <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"左にスワイプすると、コミュニティ チュートリアルが開始します"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"ウィジェット エディタを開く"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"カスタマイズ"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"閉じる"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"このスペースでのウィジェットの追加、削除、並べ替え"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"ウィジェットの追加"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"長押ししてウィジェットをカスタマイズ"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"削除"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"ウィジェットを追加"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"完了"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"BluetoothをONにしますか?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"タブレットでキーボードに接続するには、最初にBluetoothをONにする必要があります。"</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"ONにする"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"電源通知管理"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"ON - 顔ベース"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"電源通知管理では、アプリの通知の重要度をレベル 0~5 で設定できます。\n\n"<b>"レベル 5"</b>" \n- 通知リストの一番上に表示する \n- 全画面表示を許可する \n- 常にポップアップする \n\n"<b>"レベル 4"</b>" \n- 全画面表示しない \n- 常にポップアップする \n\n"<b>"レベル 3"</b>" \n- 全画面表示しない \n- ポップアップしない \n\n"<b>"レベル 2"</b>" \n- 全画面表示しない \n- ポップアップしない \n- 音やバイブレーションを使用しない \n\n"<b>"レベル 1"</b>" \n- 全画面表示しない \n- ポップアップしない \n- 音やバイブレーションを使用しない \n- ロック画面やステータスバーに表示しない \n- 通知リストの一番下に表示する \n\n"<b>"レベル 0"</b>" \n- アプリからのすべての通知をブロックする"</string> <string name="inline_done_button" msgid="6043094985588909584">"完了"</string> <string name="inline_ok_button" msgid="603075490581280343">"適用"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"通知を OFF にする"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"セットアップ"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"ストレージ"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"ヒント"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"ユーザー補助"</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> を実行中"</string> <string name="instant_apps_message" msgid="6112428971833011754">"アプリをインストールせずに開きました。"</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"タップしてユーザー補助機能を開きます。ボタンのカスタマイズや入れ替えを [設定] で行えます。\n\n"<annotation id="link">"設定を表示"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"ボタンを一時的に非表示にするには、端に移動させてください"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"元に戻す"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"ユーザー補助機能ボタンは非表示です"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"ユーザー補助機能ボタンを表示するにはタップしてください"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> のショートカットを削除しました"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# 個のショートカットを削除}other{# 個のショートカットを削除}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"左上に移動"</string> diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml index c841d1c1efbc..59d7487293b9 100644 --- a/packages/SystemUI/res/values-ka/strings.xml +++ b/packages/SystemUI/res/values-ka/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"სახით განბლოკვის დაყენება ვერ მოხერხდა. გადადით პარამეტრებზე და ცადეთ ხელახლა."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"შეეხეთ თითის ანაბეჭდის სენსორს"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"გასაგრძელებლად დააჭირეთ განბლოკვის ხატულას"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"სახის ამოცნობა ვერ მოხერხდა. ცადეთ თითის ანაბეჭდი."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"სახის ამოცნობა ვერ მოხერხდა"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"გამოიყენეთ თითის ანაბეჭდი"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"სახით განბლოკვა მიუწვდომელია."</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth დაკავშირებულია."</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • იტენება • სრულ დატენვამდე <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"გადაფურცლეთ მარცხნივ, რათა დაიწყოთ საერთო სახელმძღვანელო"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"გახსენით ვიჯეტის რედაქტორი"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"მორგება"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"უარყოფა"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"ამ სივრცეში შეძლებთ თქვენი ვიჯეტების დამატებას, ამოშლასა და გადაწყობას"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"ვიჯეტების დამატება"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"ხანგრძლივად დააჭირეთ ვიჯეტების მოსარგებად"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"ამოშლა"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"ვიჯეტის დამატება"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"მზადაა"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"გსურთ Bluetooth-ის ჩართვა?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"კლავიატურის ტაბლეტთან დასაკავშირებლად, ჯერ უნდა ჩართოთ Bluetooth."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"ჩართვა"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"შეტყობინებების მართვის საშუალებები"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"ჩართული — სახის მიხედვით"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"შეტყობინებების მართვის საშუალებების მეშვეობით, შეგიძლიათ განსაზღვროთ აპის შეტყობინებების მნიშვნელობის დონე 0-დან 5-მდე დიაპაზონში. \n\n"<b>"დონე 5"</b>" \n— შეტყობინებათა სიის თავში ჩვენება \n— სრულეკრანიანი რეჟიმის შეფერხების დაშვება \n— ეკრანზე ყოველთვის გამოჩენა \n\n"<b>"დონე 4"</b>" \n— სრულეკრანიანი რეჟიმის შეფერხების აღკვეთა \n— ეკრანზე ყოველთვის გამოჩენა \n\n"<b>"დონე 3"</b>" \n— სრულეკრანიანი რეჟიმის შეფერხების აღკვეთა \n— ეკრანზე გამოჩენის აღკვეთა \n\n"<b>"დონე 2"</b>" \n— სრულეკრანიანი რეჟიმის შეფერხების აღკვეთა \n— ეკრანზე გამოჩენის აღკვეთა \n— ხმისა და ვიბრაციის აღკვეთა \n\n"<b>"დონე 1"</b>" \n— სრულეკრანიანი რეჟიმის შეფერხების აღკვეთა \n— ეკრანზე გამოჩენის აღკვეთა \n— ხმისა და ვიბრაციის აღკვეთა \n— ჩაკეტილი ეკრანიდან და სტატუსის ზოლიდან დამალვა \n— შეტყობინებათა სიის ბოლოში ჩვენება \n\n"<b>"დონე 0"</b>" \n— აპის ყველა შეტყობინების დაბლოკვა"</string> <string name="inline_done_button" msgid="6043094985588909584">"მზადაა"</string> <string name="inline_ok_button" msgid="603075490581280343">"მისადაგება"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"შეტყობინებების გამორთვა"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"დაყენება"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"მეხსიერება"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"მინიშნებები"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"მარტივი წვდომა"</string> <string name="instant_apps" msgid="8337185853050247304">"მყისიერი აპები"</string> <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> გაშვებულია"</string> <string name="instant_apps_message" msgid="6112428971833011754">"აპი გაიხსნა ინსტალაციის გარეშე."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"შეეხეთ მარტივი წვდომის ფუნქციების გასახსნელად. მოარგეთ ან შეცვალეთ ეს ღილაკი პარამეტრებში.\n\n"<annotation id="link">"პარამეტრების ნახვა"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"გადაიტანეთ ღილაკი კიდეში, რათა დროებით დამალოთ ის"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"მოქმედების გაუქმება"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"მარტივი წვდომის ღილაკი დამალულია"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"შეეხეთ მარტივი წვდომის ღილაკის საჩვენებლად"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> მალსახმობი ამოშლილია"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# მალსახმობი ამოშლილია}other{# მალსახმობი ამოშლილია}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"ზევით და მარცხნივ გადატანა"</string> diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml index f81ad0562433..b6a18d79a395 100644 --- a/packages/SystemUI/res/values-kk/strings.xml +++ b/packages/SystemUI/res/values-kk/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Бет тану функциясы реттелмеді. \"Параметрлер\" бөліміне өтіп, әрекетті қайталап көріңіз."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Саусақ ізін оқу сканерін түртіңіз"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Жалғастыру үшін құлыпты ашу белгішесін басыңыз."</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"Бет танылмады. Орнына саусақ ізін пайдаланыңыз."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"Бет танылмады."</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Орнына саусақ ізін пайдаланыңыз."</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"Бет тану функциясы қолжетімсіз."</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth қосылған."</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Зарядталып жатыр. • Толуына <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> қалды."</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Ортақ оқулықты ашу үшін солға қарай сырғытыңыз."</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Виджет редакторын ашу"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Бейімдеу"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Жабу"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Осы бөлмеде виджеттер қосыңыз, оларды өшіріңіз және ретін өзгертіңіз."</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Басқа виджеттер қосыңыз."</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Виджеттерді бейімдеу үшін ұзақ басып тұрыңыз."</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"Өшіру"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Виджет қосу"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Дайын"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"Bluetooth функциясын қосу керек пе?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"Пернетақтаны планшетке қосу үшін алдымен Bluetooth функциясын қосу керек."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Қосу"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Қуат хабарландыруының басқару элементтері"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Қосулы – бет негізінде"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"Қуат хабарландыруының басқару элементтерімен қолданбаның хабарландырулары үшін 0-ден бастап 5-ке дейін маңыздылық деңгейін орнатуға болады. \n\n"<b>"5-деңгей"</b>" \n- Хабарландыру тізімінің ең басында көрсету \n- Толық экранға ашылуын рұқсат ету \n- Әрдайым қалқымалы хабарландыру түрінде көрсету \n\n"<b>"4-деңгей"</b>" \n- Толық экранға шығармау \n- Әрдайым қалқымалы хабарландыру түрінде көрсету \n\n"<b>"3-деңгей"</b>" \n- Толық экранға шығармау \n- Ешқашан қалқымалы хабарландыру түрінде көрсетпеу \n\n"<b>"2-деңгей"</b>" \n- Толық экранға шығармау \n- Ешқашан қалқымалы хабарландыру түрінде көрсетпеу \n- Ешқашан дыбыс және діріл шығармау \n\n"<b>"1-деңгей"</b>" \n- Толық экранға шығармау \n- Ешқашан қалқымалы хабарландыру түрінде көрсетпеу \n- Ешқашан дыбыс немесе діріл шығармау \n- Құлыпталған экраннан және күйін көрсету жолағынан жасыру \n- Хабарландыру тізімінің ең астында көрсету \n\n"<b>"0-деңгей"</b>" \n- Қолданбадағы барлық хабарландыруларға тыйым салу"</string> <string name="inline_done_button" msgid="6043094985588909584">"Дайын"</string> <string name="inline_ok_button" msgid="603075490581280343">"Қолдану"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Хабарландыруларды өшіру"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"Реттеу"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"Жад"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"Кеңестер"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"Арнайы мүмкіндіктер"</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> іске қосулы"</string> <string name="instant_apps_message" msgid="6112428971833011754">"Қолданба орнатылмай-ақ ашылды."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Арнайы мүмкіндікті ашу үшін түртіңіз. Түймені параметрден реттеңіз не ауыстырыңыз.\n\n"<annotation id="link">"Параметрді көру"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Түймені уақытша жасыру үшін оны шетке қарай жылжытыңыз."</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Қайтару"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"Арнайы мүмкіндіктер түймесі жасырылған"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Арнайы мүмкіндіктер түймесін көрсету үшін түртіңіз."</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> жылдам пәрмені өшірілді."</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# таңбаша өшірілді.}other{# таңбаша өшірілді.}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Жоғарғы сол жаққа жылжыту"</string> diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml index 09b9e1571ed6..c2551e7bce54 100644 --- a/packages/SystemUI/res/values-km/strings.xml +++ b/packages/SystemUI/res/values-km/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"មិនអាចរៀបចំការដោះសោតាមទម្រង់មុខបានទេ។ សូមចូលទៅកាន់ការកំណត់ ដើម្បីព្យាយាមម្ដងទៀត។"</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"ប៉ះឧបករណ៍ចាប់ស្នាមម្រាមដៃ"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"សូមចុចរូបដោះសោ ដើម្បីបន្ត"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"មិនស្គាល់មុខទេ។ សូមប្រើស្នាមម្រាមដៃជំនួសវិញ។"</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"មិនស្គាល់មុខ"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"ប្រើស្នាមម្រាមដៃជំនួសវិញ"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"មិនអាចប្រើការដោះសោតាមទម្រង់មុខបានទេ"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"បានតភ្ជាប់ប៊្លូធូស។"</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • កំពុងសាកថ្ម • ពេញក្នុងរយៈពេល <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"អូសទៅឆ្វេង ដើម្បីចាប់ផ្ដើមមេរៀនសហគមន៍"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"បើកកម្មវិធីកែធាតុក្រាហ្វិក"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"ប្ដូរតាមបំណង"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"ច្រានចោល"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"បញ្ចូល ដកចេញ និងតម្រៀបធាតុក្រាហ្វិករបស់អ្នកឡើងវិញនៅក្នុងលំហនេះ"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"បញ្ចូលធាតុក្រាហ្វិកច្រើនទៀត"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"ចុចឱ្យយូរ ដើម្បីប្ដូរធាតុក្រាហ្វិកតាមបំណង"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"ដកចេញ"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"បញ្ចូលធាតុក្រាហ្វិក"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"រួចរាល់"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"បើកប៊្លូធូសឬ?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"ដើម្បីភ្ជាប់ក្តារចុចរបស់អ្នកជាមួយនឹងថេប្លេតរបស់អ្នក អ្នកត្រូវតែបើកប៊្លូធូសជាមុនសិន។"</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"បើក"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"អង្គគ្រប់គ្រងការជូនដំណឹងថាមពល"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"បើក - ផ្អែកលើមុខ"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"ជាមួយអង្គគ្រប់គ្រងការជូនដំណឹងថាមពល អ្នកអាចកំណត់កម្រិតសំខាន់ពី 0 ទៅ 5 សម្រាប់ការជូនដំណឹងរបស់កម្មវិធី។ \n\n"<b>"កម្រិត 5"</b>" \n- បង្ហាញនៅផ្នែកខាងលើបញ្ជីជូនដំណឹង \n- អនុញ្ញាតការរំខានលើអេក្រង់ពេញ \n- លោតឡើងជានិច្ច \n\n"<b>"កម្រិត 4"</b>" \n- រារាំងការរំខានលើអេក្រង់ពេញ \n- លោតឡើងជានិច្ច \n\n"<b>"កម្រិត 3"</b>" \n- រារាំងការរំខានលើអេក្រង់ពេញ \n- លោតឡើងជានិច្ច \n\n"<b>"កម្រិត 2"</b>" \n- រារាំងការរំខានលើអេក្រង់ពេញ \n- លោតឡើងជានិច្ច \n- មិនបន្លឺសំឡេង ឬញ័រ \n\n"<b>"កម្រិត 1"</b>" \n- រារាំងការរំខានលើអេក្រង់ពេញ \n- លោតឡើងជានិច្ច \n- មិនបន្លឺសំឡេង ឬញ័រ \n- លាក់ពីអេក្រង់ចាក់សោ និងរបារស្ថានភាព \n- បង្ហាញនៅផ្នែកខាងក្រោមបញ្ជីជូនដំណឹង \n\n"<b>"កម្រិត 0"</b>" \n- រារាំងការជូនដំណឹងទាំងអស់ពីកម្មវិធី"</string> <string name="inline_done_button" msgid="6043094985588909584">"រួចរាល់"</string> <string name="inline_ok_button" msgid="603075490581280343">"ប្រើ"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"បិទការជូនដំណឹង"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"ការរៀបចំ"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"ទំហំផ្ទុក"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"ការសម្រួល"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"ភាពងាយស្រួល"</string> <string name="instant_apps" msgid="8337185853050247304">"កម្មវិធីប្រើភ្លាមៗ"</string> <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> កំពុងដំណើរការ"</string> <string name="instant_apps_message" msgid="6112428971833011754">"កម្មវិធីត្រូវបានបើកដោយមិនចាំបាច់ដំឡើង។"</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"ចុចដើម្បីបើកមុខងារភាពងាយស្រួល។ ប្ដូរ ឬប្ដូរប៊ូតុងនេះតាមបំណងនៅក្នុងការកំណត់។\n\n"<annotation id="link">"មើលការកំណត់"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"ផ្លាស់ទីប៊ូតុងទៅគែម ដើម្បីលាក់វាជាបណ្ដោះអាសន្ន"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"ត្រឡប់វិញ"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"បានលាក់ប៊ូតុងភាពងាយស្រួល"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"ចុច ដើម្បីបង្ហាញប៊ូតុងភាពងាយស្រួល"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"បានដកផ្លូវកាត់ <xliff:g id="FEATURE_NAME">%s</xliff:g> ចេញ"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{បានដកផ្លូវកាត់ # ចេញ}other{បានដកផ្លូវកាត់ # ចេញ}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"ផ្លាស់ទីទៅខាងលើផ្នែកខាងឆ្វេង"</string> diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml index e21715461b82..a04c95b8166f 100644 --- a/packages/SystemUI/res/values-kn/strings.xml +++ b/packages/SystemUI/res/values-kn/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"ಫೇಸ್ ಅನ್ಲಾಕ್ ಅನ್ನು ಸೆಟಪ್ ಮಾಡಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ. ಮತ್ತೊಮ್ಮೆ ಪ್ರಯತ್ನಿಸಲು, ಸೆಟ್ಟಿಂಗ್ಗಳಿಗೆ ಹೋಗಿ."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಸೆನ್ಸರ್ ಅನ್ನು ಸ್ಪರ್ಶಿಸಿ"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"ಮುಂದುವರಿಯಲು ಅನ್ಲಾಕ್ ಐಕಾನ್ ಅನ್ನು ಒತ್ತಿರಿ"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"ಮುಖ ಗುರುತಿಸಲಾಗಿಲ್ಲ. ಬದಲಿಗೆ ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಬಳಸಿ."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"ಮುಖವನ್ನು ಗುರುತಿಸಲಾಗಿಲ್ಲ"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"ಬದಲಿಗೆ ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಬಳಸಿ"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"ಫೇಸ್ ಅನ್ಲಾಕ್ ಲಭ್ಯವಿಲ್ಲ"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"ಬ್ಲೂಟೂತ್ ಸಂಪರ್ಕಗೊಂಡಿದೆ."</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ದಲ್ಲಿ ಪೂರ್ಣಗೊಳ್ಳುತ್ತದೆ"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"ಸಮುದಾಯದ ಟ್ಯುಟೋರಿಯಲ್ ಅನ್ನು ಪ್ರಾರಂಭಿಸಲು ಎಡಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"ವಿಜೆಟ್ ಎಡಿಟರ್ ಅನ್ನು ತೆರೆಯಿರಿ"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"ಕಸ್ಟಮೈಸ್ ಮಾಡಿ"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"ವಜಾಗೊಳಿಸಿ"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"ಈ ಜಾಗದಲ್ಲಿ ನಿಮ್ಮ ವಿಜೆಟ್ಗಳನ್ನು ಸೇರಿಸಿ, ತೆಗೆದುಹಾಕಿ ಮತ್ತು ಮರುಕ್ರಮಗೊಳಿಸಿ"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"ಹೆಚ್ಚಿನ ವಿಜೆಟ್ಗಳನ್ನು ಸೇರಿಸಿ"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"ವಿಜೆಟ್ಗಳನ್ನು ಕಸ್ಟಮೈಸ್ ಮಾಡಲು ದೀರ್ಘಕಾಲ ಒತ್ತಿರಿ"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"ತೆಗೆದುಹಾಕಿ"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"ವಿಜೆಟ್ ಅನ್ನು ಸೇರಿಸಿ"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"ಮುಗಿದಿದೆ"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"ಬ್ಲೂಟೂತ್ ಆನ್ ಮಾಡಬೇಕೆ?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"ನಿಮ್ಮ ಕೀಬೋರ್ಡ್ ಅನ್ನು ಟ್ಯಾಬ್ಲೆಟ್ಗೆ ಸಂಪರ್ಕಿಸಲು, ನೀವು ಮೊದಲು ಬ್ಲೂಟೂತ್ ಆನ್ ಮಾಡಬೇಕಾಗುತ್ತದೆ."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"ಆನ್ ಮಾಡಿ"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"ಪವರ್ ನೋಟಿಫಿಕೇಶನ್ ನಿಯಂತ್ರಣಗಳು"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"ಆನ್ ಆಗಿದೆ - ಮುಖ-ಆಧಾರಿತ"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"ಪವರ್ ನೋಟಿಫಿಕೇಶನ್ ನಿಯಂತ್ರಣಗಳ ಮೂಲಕ, ನೀವು ಆ್ಯಪ್ಗಳ ನೋಟಿಫಿಕೇಶನ್ಗಳನ್ನು 0 ರಿಂದ 5 ರವರೆಗಿನ ಹಂತಗಳ ಪ್ರಾಮುಖ್ಯತೆಯನ್ನು ಹೊಂದಿಸಬಹುದು. \n\n"<b>"ಹಂತ 5"</b>" \n- ಮೇಲಿನ ನೋಟಿಫಿಕೇಶನ್ ಪಟ್ಟಿಯನ್ನು ತೋರಿಸಿ \n- ಪೂರ್ಣ ಪರದೆ ಅಡಚಣೆಯನ್ನು ಅನುಮತಿಸಿ \n- ಯಾವಾಗಲು ಇಣುಕು ನೋಟ \n\n"<b>"ಹಂತ 4"</b>" \n- ಪೂರ್ಣ ಪರದೆ ಅಡಚಣೆಯನ್ನು ತಡೆಯಿರಿ \n- ಯಾವಾಗಲು ಇಣುಕು ನೋಟ\n\n"<b>"ಹಂತ 3"</b>" \n- ಪೂರ್ಣ ಪರದೆ ಅಡಚಣೆಯನ್ನು ತಡೆಯಿರಿ \n- ಎಂದಿಗೂ ಇಣುಕು ನೋಟ ಬೇಡ \n\n"<b>"ಹಂತ 2"</b>" \n- ಪೂರ್ಣ ಪರದೆ ಅಡಚಣೆಯನ್ನು ತಡೆಯಿರಿ \n- ಎಂದಿಗೂ ಇಣುಕು ನೋಟ ಬೇಡ \n- ಶಬ್ದ ಮತ್ತು ವೈಬ್ರೇಷನ್ ಎಂದಿಗೂ ಮಾಡಬೇಡಿ \n\n"<b>"ಹಂತ 1"</b>" \n- ಪೂರ್ಣ ಪರದೆ ಅಡಚಣೆಯನ್ನು ತಡೆಯಿರಿ \n- ಎಂದಿಗೂ ಇಣುಕು ನೋಟ ಬೇಡ \n- ಶಬ್ದ ಮತ್ತು ವೈಬ್ರೇಷನ್ ಎಂದಿಗೂ ಮಾಡಬೇಡಿ \n- ಸ್ಥಿತಿ ಪಟ್ಟಿ ಮತ್ತು ಲಾಕ್ ಪರದೆಯಿಂದ ಮರೆಮಾಡಿ \n- ಕೆಳಗಿನ ನೋಟಿಫಿಕೇಶನ್ ಪಟ್ಟಿಯನ್ನು ತೋರಿಸಿ \n\n"<b>"ಹಂತ 0"</b>" \n- ಆ್ಯಪ್ನಿಂದ ಎಲ್ಲಾ ನೋಟಿಫಿಕೇಶನ್ಗಳನ್ನು ನಿರ್ಬಂಧಿಸಿ"</string> <string name="inline_done_button" msgid="6043094985588909584">"ಪೂರ್ಣಗೊಂಡಿದೆ"</string> <string name="inline_ok_button" msgid="603075490581280343">"ಅನ್ವಯಿಸಿ"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"ಅಧಿಸೂಚನೆಗಳನ್ನು ಆಫ್ ಮಾಡಿ"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"ಸೆಟಪ್"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"ಸಂಗ್ರಹಣೆ"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"ಸುಳಿವುಗಳು"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"ಆ್ಯಕ್ಸೆಸಿಬಿಲಿಟಿ"</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> ರನ್ ಆಗುತ್ತಿದೆ"</string> <string name="instant_apps_message" msgid="6112428971833011754">"ಇನ್ಸ್ಟಾಲ್ ಮಾಡದೆ ಆ್ಯಪ್ ತೆರೆಯಲಾಗಿದೆ."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"ಆ್ಯಕ್ಸೆಸಿಬಿಲಿಟಿ ವೈಶಿಷ್ಟ್ಯಗಳನ್ನು ತೆರೆಯಲು ಟ್ಯಾಪ್ ಮಾಡಿ. ಸೆಟ್ಟಿಂಗ್ಗಳಲ್ಲಿ ಈ ಬಟನ್ ಅನ್ನು ಕಸ್ಟಮೈಸ್ ಮಾಡಿ ಅಥವಾ ಬದಲಾಯಿಸಿ.\n\n"<annotation id="link">"ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ವೀಕ್ಷಿಸಿ"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"ಅದನ್ನು ತಾತ್ಕಾಲಿಕವಾಗಿ ಮರೆಮಾಡಲು ಅಂಚಿಗೆ ಬಟನ್ ಸರಿಸಿ"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"ರದ್ದುಗೊಳಿಸಿ"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"ಆ್ಯಕ್ಸೆಸಿಬಿಲಿಟಿ ಬಟನ್ ಅನ್ನು ಮರೆಮಾಡಲಾಗಿದೆ"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"ಆ್ಯಕ್ಸೆಸಿಬಿಲಿಟಿ ಬಟನ್ ತೋರಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> ಶಾರ್ಟ್ಕಟ್ ತೆಗೆದುಹಾಕಲಾಗಿದೆ"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# ಶಾರ್ಟ್ಕಟ್ ತೆಗೆದುಹಾಕಲಾಗಿದೆ}one{# ಶಾರ್ಟ್ಕಟ್ಗಳನ್ನು ತೆಗೆದುಹಾಕಲಾಗಿದೆ}other{# ಶಾರ್ಟ್ಕಟ್ಗಳನ್ನು ತೆಗೆದುಹಾಕಲಾಗಿದೆ}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"ಎಡ ಮೇಲ್ಭಾಗಕ್ಕೆ ಸರಿಸಿ"</string> diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml index 940b66dcef2a..e199783ca050 100644 --- a/packages/SystemUI/res/values-ko/strings.xml +++ b/packages/SystemUI/res/values-ko/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"얼굴 인식 잠금 해제를 설정할 수 없습니다. 설정으로 이동하여 다시 시도해 보세요."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"지문 센서를 터치하세요."</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"계속하려면 잠금 해제 아이콘을 누르세요."</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"얼굴을 인식할 수 없습니다. 대신 지문을 사용하세요."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"얼굴을 인식할 수 없습니다."</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"대신 지문을 사용하세요."</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"얼굴 인식 잠금 해제를 사용할 수 없습니다."</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"블루투스가 연결되었습니다."</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 충전 중 • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> 후 충전 완료"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"공동 튜토리얼을 시작하려면 왼쪽으로 스와이프하세요"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"위젯 편집기 열기"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"맞춤설정"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"닫기"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"이 공간에서 위젯 추가, 삭제 또는 다시 정렬"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"더 많은 위젯 추가"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"위젯을 맞춤설정하려면 길게 누르기"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"삭제"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"위젯 추가"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"완료"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"블루투스를 켜시겠습니까?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"키보드를 태블릿에 연결하려면 먼저 블루투스를 켜야 합니다."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"사용"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"전원 알림 컨트롤"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"켜짐 - 얼굴 기준"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"전원 알림 컨트롤을 사용하면 앱 알림 관련 중요도를 0부터 5까지로 설정할 수 있습니다. \n\n"<b>"레벨 5"</b>" \n- 알림 목록 상단에 표시 \n- 전체 화면일 경우 알림 표시 허용 \n- 항상 엿보기 표시 \n\n"<b>"레벨 4"</b>" \n- 전체 화면에 알림 표시 금지 \n- 항상 엿보기 표시 \n\n"<b>"레벨 3"</b>" \n- 전체 화면에 알림 표시 금지 \n- 엿보기 표시 안함 \n\n"<b>"레벨 2"</b>" \n- 전체 화면에 알림 표시 금지 \n- 엿보기 표시 안함 \n- 소리나 진동으로 알리지 않음 \n\n"<b>"레벨 1"</b>" \n- 전체 화면에 알림 표시 금지 \n- 엿보기 표시 안함 \n- 소리나 진동으로 알리지 않음 \n- 잠금 화면 및 상태 표시줄에서 숨김 \n- 알림 목록 하단에 표시 \n\n"<b>"레벨 0"</b>" \n- 앱의 모든 알림 차단"</string> <string name="inline_done_button" msgid="6043094985588909584">"완료"</string> <string name="inline_ok_button" msgid="603075490581280343">"적용"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"알림 사용 중지"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"설정"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"저장용량"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"힌트"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"접근성"</string> <string name="instant_apps" msgid="8337185853050247304">"인스턴트 앱"</string> <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> 실행 중"</string> <string name="instant_apps_message" msgid="6112428971833011754">"설치 없이 앱이 실행되었습니다."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"접근성 기능을 열려면 탭하세요. 설정에서 이 버튼을 맞춤설정하거나 교체할 수 있습니다.\n\n"<annotation id="link">"설정 보기"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"버튼을 가장자리로 옮겨서 일시적으로 숨기세요."</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"실행취소"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"접근성 버튼 숨김"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"탭하여 접근성 버튼 표시"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> 바로가기 삭제됨"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{바로가기 #개 삭제됨}other{바로가기 #개 삭제됨}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"왼쪽 상단으로 이동"</string> diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml index a6234c3c32d9..e42dc71f539f 100644 --- a/packages/SystemUI/res/values-ky/strings.xml +++ b/packages/SystemUI/res/values-ky/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Жүзүнөн таанып ачуу функциясы кошулган жок. Параметрлерге өтүп, кайталап көрүңүз."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Манжа изинин сенсорун басыңыз"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Улантуу үчүн кулпусун ачуу сүрөтчөсүн басыңыз"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"Жүз таанылган жок. Манжа изин колдонуңуз."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"Жүз таанылган жок"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Манжа изин колдонуңуз"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"\"Жүзүнөн таанып ачуу\" жеткиликсиз"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth байланышта"</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Кубатталууда • Толгонго чейин <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> калды"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Жалпы үйрөткүчтү иштетүү үчүн солго сүрүңүз"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Виджет түзөткүчтү ачуу"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Ыңгайлаштыруу"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Жабуу"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Бул иш чөйрөсүнө виджеттерди кошуп, өчүрүп жана иретин өзгөртүңүз"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Көбүрөөк виджеттерди кошуу"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Виджеттерди ыңгайлаштыруу үчүн кое бербей басып туруңуз"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"Өчүрүү"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Виджет кошуу"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Бүттү"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"Bluetooth күйгүзүлсүнбү?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"Баскычтобуңузду планшетиңизге туташтыруу үчүн, адегенде Bluetooth\'ту күйгүзүшүңүз керек."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Күйгүзүү"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Эскертмелерди башкаруу каражаттары"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Күйүк – Жүздүн негизинде"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"Бул функциянын жардамы менен, ар бир колдонмо үчүн билдирменин маанилүүлүгүн 0дон 5ке чейин бааласаңыз болот. \n\n"<b>"5-деңгээл"</b>" \n- Билдирмелер тизмесинин өйдө жагында көрүнөт \n- Билдирмелер толук экранда көрүнөт \n- Калкып чыгуучу билдирмелерге уруксат берилет \n\n"<b>"4-деңгээл"</b>" \n- Билдирмелер толук экранда көрүнбөйт \n- Калкып чыгуучу билдирмелерге уруксат берилет \n\n"<b>"3-деңгээл"</b>" \n- Билдирмелер толук экранда көрүнбөйт \n- Калкып чыгуучу билдирмелерге тыюу салынат \n\n"<b>"2-деңгээл"</b>" \n- Билдирмелер толук экранда көрүнбөйт \n- Калкып чыгуучу билдирмелерге тыюу салынат \n- Эч качан үн чыкпайт же дирилдебейт \n\n"<b>"1-деңгээл"</b>" \n- Билдирмелер толук экранда көрүнбөйт \n- Калкып чыгуучу билдирмелерге тыюу салынат \n- Эч качан үн чыкпайт же дирилдебейт \n- Кулпуланган экрандан жана абал тилкесинен жашырылат \n- Билдирмелер тизмесинин ылдый жагында көрүнөт \n\n"<b>"0-деңгээл"</b>" \n- Колдонмодон алынган бардык билдирмелер бөгөттөлөт"</string> <string name="inline_done_button" msgid="6043094985588909584">"Бүттү"</string> <string name="inline_ok_button" msgid="603075490581280343">"Колдонуу"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Билдирмелерди өчүрүү"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"Тууралоо"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"Сактагыч"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"Кеңештер"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"Атайын мүмкүнчүлүктөр"</string> <string name="instant_apps" msgid="8337185853050247304">"Ыкчам ачылуучу колдонмолор"</string> <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> иштеп жатат"</string> <string name="instant_apps_message" msgid="6112428971833011754">"Колдонмо орнотулбастан ачылды."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Атайын мүмкүнчүлүктөрдү ачуу үчүн басыңыз. Бул баскычты Параметрлерден өзгөртүңүз.\n\n"<annotation id="link">"Параметрлерди көрүү"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Баскычты убактылуу жашыра туруу үчүн экрандын четине жылдырыңыз"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Кайтаруу"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"Атайын мүмкүнчүлүктөр баскычы жашырылган"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Атайын мүмкүнчүлүктөр баскычын көрсөтүү үчүн таптаңыз"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> ыкчам баскычы өчүрүлдү"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# ыкчам баскыч өчүрүлдү}other{# ыкчам баскыч өчүрүлдү}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Жогорку сол жакка жылдыруу"</string> diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml index 87ca72255cbb..ea12242d3684 100644 --- a/packages/SystemUI/res/values-lo/strings.xml +++ b/packages/SystemUI/res/values-lo/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"ບໍ່ສາມາດຕັ້ງຄ່າການປົດລັອກດ້ວຍໜ້າໄດ້. ກະລຸນາເຂົ້າໄປການຕັ້ງຄ່າເພື່ອລອງໃໝ່."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"ແຕະໃສ່ເຊັນເຊີລາຍນິ້ວມື"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"ກົດໄອຄອນປົດລັອກເພື່ອສືບຕໍ່"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"ບໍ່ສາມາດຈຳແນກໜ້າໄດ້. ໃຊ້ລາຍນິ້ວມືແທນ."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"ບໍ່ສາມາດຈຳແນກໜ້າໄດ້"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"ກະລຸນາໃຊ້ລາຍນິ້ວມືແທນ"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"ໃຊ້ການປົດລັອກດ້ວຍໜ້າບໍ່ໄດ້"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"ເຊື່ອມຕໍ່ Bluetooth ແລ້ວ."</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ກຳລັງສາກໄຟ • ຈະເຕັມໃນອີກ <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"ປັດຊ້າຍເພື່ອເລີ່ມບົດແນະນຳສ່ວນກາງ"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"ເປີດຕົວແກ້ໄຂວິດເຈັດ"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"ປັບແຕ່ງ"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"ປ່ອຍໄປ"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"ເພີ່ມ, ລຶບອອກ ແລະ ຈັດຮຽງວິດເຈັດຂອງທ່ານຄືນໃໝ່ໃນພື້ນທີ່ນີ້"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"ເພີ່ມວິດເຈັດເພີ່ມເຕີມ"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"ກົດຄ້າງໄວ້ເພື່ອປັບແຕ່ງວິດເຈັດ"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"ລຶບອອກ"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"ເພີ່ມວິດເຈັດ"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"ແລ້ວໆ"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"ເປີດໃຊ້ Bluetooth ບໍ່?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"ເພື່ອເຊື່ອມຕໍ່ແປ້ນພິມຂອງທ່ານກັບແທັບເລັດຂອງທ່ານ, ກ່ອນອື່ນໝົດທ່ານຕ້ອງເປີດ Bluetooth."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"ເປີດ"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"ການຄວບຄຸມການແຈ້ງເຕືອນ"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"ເປີດ - ອ້າງອີງໃບໜ້າ"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"ດ້ວຍການຄວບຄຸມການແຈ້ງເຕືອນ, ທ່ານສາມາດຕັ້ງລະດັບຄວາມສຳຄັນຈາກ 0 ຮອດ 5 ໃຫ້ກັບການແຈ້ງເຕືອນແອັບໃດໜຶ່ງໄດ້. \n\n"<b>"ລະດັບ 5"</b>" \n- ສະແດງຢູ່ເທິງສຸດຂອງລາຍການແຈ້ງເຕືອນ \n- ອະນຸຍາດໃຫ້ຂັດຈັງຫວະຕອນເປີດເຕັມຈໍ \n- ແນມເບິ່ງທຸກເທື່ອ \n\n"<b>"ລະດັບ 4"</b>" \n- ກັນບໍ່ໃຫ້ຂັດຈັງຫວະຕອນເປີດເຕັມຈໍ \n- ແນມເບິ່ງທຸກເທື່ອ \n\n"<b>"ລະດັບ 3"</b>" \n- ກັນບໍ່ໃຫ້ຂັດຈັງຫວະຕອນເປີດເຕັມຈໍ \n- ບໍ່ແນມເບິ່ງ \n\n"<b>"ລະດັບ 2"</b>" \n- ກັນບໍ່ໃຫ້ຂັດຈັງຫວະຕອນເປີດເຕັມຈໍ \n- ບໍ່ແນມເບິ່ງ \n- ບໍ່ມີສຽງ ແລະ ບໍ່ມີການສັ່ນເຕືອນ \n\n"<b>"ລະດັບ 1"</b>" \n- ກັນບໍ່ໃຫ້ຂັດຈັງຫວະຕອນເປີດເຕັມຈໍ \n- ບໍ່ແນມເບິ່ງ \n- ບໍ່ມີສຽງ ແລະ ບໍ່ມີການສັ່ນເຕືອນ \n- ເຊື່ອງຈາກໜ້າຈໍລັອກ ແລະ ແຖບສະຖານະ \n- ສະແດງຢູ່ລຸ່ມສຸດຂອງລາຍການແຈ້ງເຕືອນ \n\n"<b>"ລະດັບ 0"</b>" \n- ປິດກັ້ນການແຈ້ງເຕືອນທັງໝົດຈາກແອັບ"</string> <string name="inline_done_button" msgid="6043094985588909584">"ແລ້ວໆ"</string> <string name="inline_ok_button" msgid="603075490581280343">"ນຳໃຊ້"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"ປິດການແຈ້ງເຕືອນ"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"ຕັ້ງຄ່າ"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"ບ່ອນເກັບຂໍ້ມູນ"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"ຄຳໃບ້"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"ການຊ່ວຍເຂົ້າເຖິງ"</string> <string name="instant_apps" msgid="8337185853050247304">"ອິນສະແຕນແອັບ"</string> <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> ກຳລັງເຮັດວຽກຢູ່"</string> <string name="instant_apps_message" msgid="6112428971833011754">"ເປີດແອັບໂດຍບໍ່ມີການຕິດຕັ້ງແລ້ວ."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"ແຕະເພື່ອເປີດຄຸນສົມບັດການຊ່ວຍເຂົ້າເຖິງ. ປັບແຕ່ງ ຫຼື ປ່ຽນປຸ່ມນີ້ໃນການຕັ້ງຄ່າ.\n\n"<annotation id="link">"ເບິ່ງການຕັ້ງຄ່າ"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"ຍ້າຍປຸ່ມໄປໃສ່ຂອບເພື່ອເຊື່ອງມັນຊົ່ວຄາວ"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"ຍົກເລີກ"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"ປຸ່ມການຊ່ວຍເຂົ້າເຖິງຖືກເຊື່ອງໄວ້"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"ແຕະເພື່ອສະແດງປຸ່ມການຊ່ວຍເຂົ້າເຖິງ"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"ລຶບທາງລັດ <xliff:g id="FEATURE_NAME">%s</xliff:g> ອອກແລ້ວ"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{ລຶບ # ທາງລັດອອກແລ້ວ}other{ລຶບ # ທາງລັດອອກແລ້ວ}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"ຍ້າຍຊ້າຍເທິງ"</string> diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml index eee0f7dddcb2..38a25e5a95e9 100644 --- a/packages/SystemUI/res/values-lt/strings.xml +++ b/packages/SystemUI/res/values-lt/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Nepavyko nustatyti atrakinimo pagal veidą. Eikite į skiltį „Nustatymai“ ir bandykite dar kartą."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Palieskite piršto antspaudo jutiklį"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Tęskite paspaudę atrakinimo piktogramą"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"Veidas neatpažintas. Naudokite piršto antspaudą."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"Veidas neatpažintas"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Naudoti piršto antspaudą"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"Atrakinimo pagal veidą funkcija nepasiekiama"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"„Bluetooth“ prijungtas."</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Įkraunama • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> iki visiško įkrovimo"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Perbraukite kairėn, paleistumėte bendruomenės mokomąją medžiagą"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Atidaryti valdiklio redagavimo programą"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Tinkinti"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Atsisakyti"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Šioje erdvėje pridėkite valdiklių, juos pašalinkite ir keiskite jų tvarką"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Pridėkite daugiau valdiklių"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Ilgai paspauskite, kad tinkintumėte valdiklius"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"Pašalinti"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Pridėti valdiklį"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Atlikta"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"Įjungti „Bluetooth“?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"Kad galėtumėte prijungti klaviatūrą prie planšetinio kompiuterio, pirmiausia turite įjungti „Bluetooth“."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Įjungti"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Galingi pranešimų valdikliai"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Įjungta – pagal veidą"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"Naudodami pranešimų valdiklius galite nustatyti programos pranešimų svarbos lygį nuo 0 iki 5. \n\n"<b>"5 lygis"</b>" \n– Rodyti pranešimų sąrašo viršuje \n– Leisti pertraukti, kai veikia viso ekrano režimas \n– Visada rodyti pranešimus \n\n"<b>"4 lygis"</b>" \n– Neleisti pertraukti viso ekrano režimo \n– Visada rodyti pranešimus \n\n"<b>"3 lygis"</b>" \n– Neleisti pertraukti viso ekrano režimo \n– Niekada nerodyti pranešimų \n\n"<b>"2 lygis"</b>" \n– Neleisti pertraukti viso ekrano režimo \n– Niekada nerodyti pranešimų \n– Niekada neleisti garso ir nevibruoti \n\n"<b>"1 lygis"</b>" \n– Neleisti pertraukti viso ekrano režimo \n– Niekada nerodyti pranešimų \n– Niekada neleisti garso ir nevibruoti \n– Slėpti užrakinimo ekrane ir būsenos juostoje \n– Rodyti pranešimų sąrašo apačioje \n\n"<b>"0 lygis"</b>" \n– Blokuoti visus programos pranešimus"</string> <string name="inline_done_button" msgid="6043094985588909584">"Atlikta"</string> <string name="inline_ok_button" msgid="603075490581280343">"Taikyti"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Išjungti pranešimus"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"Sąranka"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"Saugykla"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"Užuominos"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"Pritaikomumas"</string> <string name="instant_apps" msgid="8337185853050247304">"Akimirksniu įkeliamos programos"</string> <string name="instant_apps_title" msgid="8942706782103036910">"Programa „<xliff:g id="APP">%1$s</xliff:g>“ paleista"</string> <string name="instant_apps_message" msgid="6112428971833011754">"Programa atidaryta jos neįdiegus."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Palietę atidarykite pritaikymo neįgaliesiems funkcijas. Tinkinkite arba pakeiskite šį mygtuką nustatymuose.\n\n"<annotation id="link">"Žr. nustatymus"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Perkelkite mygtuką prie krašto, kad laikinai jį paslėptumėte"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Anuliuoti"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"Pritaikomumo mygtukas paslėptas"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Palieskite, kad būtų rodomas pritaikomumo mygtukas"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Pašalintas spart. klavišas „<xliff:g id="FEATURE_NAME">%s</xliff:g>“"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{Pašalintas # spartusis klavišas}one{Pašalintas # spartusis klavišas}few{Pašalinti # spartieji klavišai}many{Pašalinta # sparčiojo klavišo}other{Pašalinta # sparčiųjų klavišų}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Perkelti į viršų kairėje"</string> diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml index 8631d207c766..bea683b22f37 100644 --- a/packages/SystemUI/res/values-lv/strings.xml +++ b/packages/SystemUI/res/values-lv/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Nevarēja iestatīt autorizāciju pēc sejas. Atveriet iestatījumus, lai mēģinātu vēlreiz."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Pieskarieties pirksta nospieduma sensoram"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Lai turpinātu, nospiediet atbloķēšanas ikonu."</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"Seja netika atpazīta. Lietojiet pirksta nospiedumu."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"Seja netika atpazīta."</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Lietot pirksta nospiedumu"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"Autorizācija pēc sejas nav pieejama"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth savienojums ir izveidots."</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Notiek uzlāde • Laiks līdz pilnai uzlādei: <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Velciet pa kreisi, lai palaistu kopienas pamācību."</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Atvērt logrīku redaktoru"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Pielāgot"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Nerādīt"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Šajā vietā varat pievienot, noņemt un pārkārtot logrīkus"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Pievienot citus logrīkus"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Nospiediet un turiet, lai pielāgotu logrīkus."</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"Noņemt"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Pievienot logrīku"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Gatavs"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"Vai ieslēgt Bluetooth savienojumu?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"Lai pievienotu tastatūru planšetdatoram, vispirms ir jāieslēdz Bluetooth savienojums."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Ieslēgt"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Barošanas paziņojumu vadīklas"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Ieslēgta — ar sejas noteikšanu"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"Izmantojot barošanas paziņojumu vadīklas, varat lietotnes paziņojumiem iestatīt svarīguma līmeni (no 0 līdz 5). \n\n"<b>"5. līmenis"</b>" \n- Tiek rādīts paziņojumu saraksta augšdaļā \n- Tiek atļauta pilnekrāna režīma pārtraukšana \n- Ieskats vienmēr atļauts \n\n"<b>"4. līmenis"</b>" \n- Tiek novērsta pilnekrāna režīma pārtraukšana \n- Ieskats vienmēr atļauts \n\n"<b>"3. līmenis"</b>" \n- Tiek novērsta pilnekrāna režīma pārtraukšana \n- Ieskats nav atļauts \n\n"<b>"2. līmenis"</b>" \n- Tiek novērsta pilnekrāna režīma pārtraukšana \n- Ieskats nav atļauts \n- Nav atļautas skaņas un vibrosignāls \n\n"<b>"1. līmenis"</b>" \n- Tiek novērsta pilnekrāna režīma pārtraukšana \n- Ieskats nav atļauts \n- Nav atļautas skaņas un vibrosignāls \n- Paziņojumi tiek paslēpti bloķēšanas ekrānā un statusa joslā \n- Paziņojumi tiek rādīti paziņojumu saraksta apakšdaļā \n\n"<b>"0. līmenis"</b>" \n- Visi lietotnes paziņojumi tiek bloķēti"</string> <string name="inline_done_button" msgid="6043094985588909584">"Gatavs"</string> <string name="inline_ok_button" msgid="603075490581280343">"Lietot"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Izslēgt paziņojumus"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"Iestatīšana"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"Krātuve"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"Padomi"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"Pieejamība"</string> <string name="instant_apps" msgid="8337185853050247304">"Tūlītējās lietotnes"</string> <string name="instant_apps_title" msgid="8942706782103036910">"Lietotne <xliff:g id="APP">%1$s</xliff:g> darbojas"</string> <string name="instant_apps_message" msgid="6112428971833011754">"Lai atvērtu šo lietotni, tā nav jāinstalē."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Atveriet pieejamības funkcijas. Pielāgojiet vai aizstājiet šo pogu iestatījumos.\n\n"<annotation id="link">"Skatīt iestatījumus"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Lai īslaicīgi paslēptu pogu, pārvietojiet to uz malu"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Atsaukt"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"Pieejamības poga ir paslēpta"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Pieskarieties, lai tiktu parādīta pieejamības poga."</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Noņemts īsinājumtaustiņš <xliff:g id="FEATURE_NAME">%s</xliff:g>"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{Noņemts # īsinājumtaustiņš}zero{Noņemti # īsinājumtaustiņi}one{Noņemts # īsinājumtaustiņš}other{Noņemti # īsinājumtaustiņi}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Pārvietot augšpusē pa kreisi"</string> diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml index 8f7c2694db62..26192e5a815c 100644 --- a/packages/SystemUI/res/values-mk/strings.xml +++ b/packages/SystemUI/res/values-mk/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Не можеше да се постави „Отклучување со лик“. Отворете „Поставки“ за да се обидете повторно."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Допрете го сензорот за отпечатоци"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Притиснете ја иконата за отклучување за да продолжите"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"Ликот не е препознаен. Користете отпечаток."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"Ликот не е препознаен"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Користи отпечаток"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"„Отклучувањето со лик“ е недостапно"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth е поврзан."</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Се полни • Полна по <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Повлечете налево за да го започнете заедничкото упатство"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Го отвора уредникот на виџети"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Приспособете"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Отфрли"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Додајте, отстранете и прераспоредете ги виџетите во просторов"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Додајте повеќе виџети"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Притиснете долго за да ги приспособите виџетите"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"Отстранува"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Додајте виџет"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Готово"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"Да се вклучи Bluetooth?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"За да ја поврзете тастатурата со таблетот, најпрво треба да вклучите Bluetooth."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Вклучи"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Контроли за известувањата за напојување"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Вклучено - според лице"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"Со контролите за известувањата за напојување, може да поставите ниво на важност од 0 до 5 за известувањата на која било апликација. \n\n"<b>"Ниво 5"</b>" \n- Прикажувај на врвот на списокот со известувања \n- Дозволи прекин во цел екран \n- Секогаш користи појавување \n\n"<b>"Ниво 4"</b>" \n- Спречи прекин во цел екран \n- Секогаш користи појавување \n\n"<b>"Ниво 3"</b>" \n- Спречи прекин во цел екран \n- Без појавување \n\n"<b>"Ниво 2"</b>" \n- Спречи прекин во цел екран \n- Без појавување \n- Без звук и вибрации \n\n"<b>"Ниво 1"</b>" \n- Спречи прекин во цел екран \n- Без појавување \n- Без звук и вибрации \n- Скриј од заклучен екран и статусна лента \n- Прикажувај на дното на списокот со известувања \n\n"<b>"Ниво 0"</b>" \n- Блокирај ги сите известувања од апликацијата"</string> <string name="inline_done_button" msgid="6043094985588909584">"Готово"</string> <string name="inline_ok_button" msgid="603075490581280343">"Примени"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Исклучи известувања"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"Поставување"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"Капацитет"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"Совети"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"Пристапност"</string> <string name="instant_apps" msgid="8337185853050247304">"Инстант апликации"</string> <string name="instant_apps_title" msgid="8942706782103036910">"Се извршува <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="instant_apps_message" msgid="6112428971833011754">"Апликацијата беше отворена без да се инсталира."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Допрете за функциите за пристапност. Приспособете или заменете го копчево во „Поставки“.\n\n"<annotation id="link">"Прикажи поставки"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Преместете го копчето до работ за да го сокриете привремено"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Врати"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"Копчето за пристапност е скриено"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Допрете за да се прикаже копчето за пристапност"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Кратенката за „<xliff:g id="FEATURE_NAME">%s</xliff:g>“ е отстранета"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{Отстранета е # кратенка}one{Отстранети се # кратенка}other{Отстранети се # кратенки}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Премести горе лево"</string> diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml index 6f8ebc9073bf..8d3a8cc1fb29 100644 --- a/packages/SystemUI/res/values-ml/strings.xml +++ b/packages/SystemUI/res/values-ml/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"ഫെയ്സ് അൺലോക്ക് സജ്ജീകരിക്കാനായില്ല. വീണ്ടും ശ്രമിക്കാൻ ക്രമീകരണത്തിലേക്ക് പോകുക."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"ഫിംഗർപ്രിന്റ് സെൻസർ സ്പർശിക്കുക"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"തുടരാൻ അൺലോക്ക് ഐക്കൺ അമർത്തുക"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"മുഖം തിരിച്ചറിഞ്ഞിട്ടില്ല. പകരം ഫിംഗർപ്രിന്റ് ഉപയോഗിക്കൂ."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"മുഖം തിരിച്ചറിഞ്ഞിട്ടില്ല"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"പകരം ഫിംഗർപ്രിന്റ് ഉപയോഗിക്കൂ"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"ഫെയ്സ് അൺലോക്ക് ലഭ്യമല്ല"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"ബ്ലൂടൂത്ത് കണക്റ്റുചെയ്തു."</string> @@ -419,8 +417,7 @@ <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"ഡിസ്മിസ് ചെയ്യുക"</string> <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"ഈ സ്പെയ്സിൽ നിങ്ങളുടെ വിജറ്റുകൾ ചേർക്കുക, നീക്കം ചെയ്യുക, പുനഃക്രമീകരിക്കുക"</string> <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"കൂടുതൽ വിജറ്റുകൾ ചേർക്കുക"</string> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"വിജറ്റുകൾ ഇഷ്ടാനുസൃതമാക്കാൻ ദീർഘനേരം അമർത്തുക"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"നീക്കം ചെയ്യുക"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"വിജറ്റ് ചേർക്കുക"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"പൂർത്തിയായി"</string> @@ -607,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"Bluetooth ഓണാക്കണോ?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"നിങ്ങളുടെ ടാബ്ലെറ്റുമായി കീബോർഡ് കണക്റ്റുചെയ്യുന്നതിന്, ആദ്യം Bluetooth ഓണാക്കേണ്ടതുണ്ട്."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"ഓണാക്കുക"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"പവർ അറിയിപ്പ് നിയന്ത്രണങ്ങൾ"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"ഓണാണ് - ഫേസ് ബേസ്ഡ്"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"പവർ അറിയിപ്പ് നിയന്ത്രണം ഉപയോഗിച്ച്, ഒരു ആപ്പിനായുള്ള അറിയിപ്പുകൾക്ക് 0 മുതൽ 5 വരെയുള്ള പ്രാധാന്യ ലെവലുകളിലൊന്ന് നിങ്ങൾക്ക് സജ്ജമാക്കാവുന്നതാണ്. \n\n"<b>"ലെവൽ 5"</b>" \n- അറിയിപ്പ് ലിസ്റ്റിന്റെ മുകളിൽ കാണിക്കുക \n- മുഴുവൻ സ്ക്രീൻ തടസ്സം അനുവദിക്കുക \n- എല്ലായ്പ്പോഴും ദൃശ്യമാക്കുക \n\n"<b>"ലെവൽ 4"</b>" \n- മുഴുവൻ സ്ക്രീൻ തടസ്സം തടയുക \n- എല്ലായ്പ്പോഴും ദൃശ്യമാക്കുക \n\n"<b>"ലെവൽ 3"</b>" \n- മുഴുവൻ സ്ക്രീൻ തടസ്സം തടയുക \n- ഒരിക്കലും സൃശ്യമാക്കരുത് \n\n"<b>"ലെവൽ 2"</b>" \n- മുഴുവൻ സ്ക്രീൻ തടസ്സം തടയുക \n- ഒരിക്കലും ദൃശ്യമാക്കരുത് \n- ഒരിക്കലും ശബ്ദവും വൈബ്രേഷനും ഉണ്ടാക്കരുത് \n\n"<b>"ലെവൽ 1"</b>" \n- മുഴുവൻ സ്ക്രീൻ തടസ്സം തടയുക \n- ഒരിക്കലും ദൃശ്യമാക്കരുത് \n- ഒരിക്കലും ശബ്ദവും വൈബ്രേഷനും ഉണ്ടാക്കരുത് \n- ലോക്ക് സ്ക്രീനിൽ നിന്നും സ്റ്റാറ്റസ് ബാറിൽ നിന്നും മറയ്ക്കുക \n- അറിയിപ്പ് ലിസ്റ്റിന്റെ അടിയിൽ കാണിക്കുക \n\n"<b>"ലെവൽ 0"</b>" \n- ആപ്പിൽ നിന്നുള്ള എല്ലാ അറിയിപ്പുകളും ബ്ലോക്കുചെയ്യുക"</string> <string name="inline_done_button" msgid="6043094985588909584">"പൂർത്തിയായി"</string> <string name="inline_ok_button" msgid="603075490581280343">"ബാധകമാക്കുക"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"അറിയിപ്പുകൾ ഓഫാക്കുക"</string> @@ -842,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"സജ്ജീകരണം"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"സ്റ്റോറേജ്"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"സൂചനകൾ"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"ഉപയോഗസഹായി"</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> റണ് ചെയ്യുന്നു"</string> <string name="instant_apps_message" msgid="6112428971833011754">"ഇൻസ്റ്റാൾ ചെയ്യാതെ ആപ്പ് തുറന്നു."</string> @@ -939,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"ഉപയോഗസഹായി ഫീച്ചർ തുറക്കാൻ ടാപ്പ് ചെയ്യൂ. ക്രമീകരണത്തിൽ ഈ ബട്ടൺ ഇഷ്ടാനുസൃതമാക്കാം, മാറ്റാം.\n\n"<annotation id="link">"ക്രമീകരണം കാണൂ"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"തൽക്കാലം മറയ്ക്കുന്നതിന് ബട്ടൺ അരുകിലേക്ക് നീക്കുക"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"പഴയപടിയാക്കുക"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"ഉപയോഗസഹായി ബട്ടൺ മറച്ചിരിക്കുന്നു"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"ഉപയോഗസഹായി ബട്ടൺ കാണിക്കുന്നതിന് ടാപ്പ് ചെയ്യുക"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> കുറുക്കുവഴി നീക്കം ചെയ്തു"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# കുറുക്കുവഴി നീക്കം ചെയ്തു}other{# കുറുക്കുവഴികൾ നീക്കം ചെയ്തു}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"മുകളിൽ ഇടതുഭാഗത്തേക്ക് നീക്കുക"</string> diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml index cb0eff5a18e1..3380af485cfe 100644 --- a/packages/SystemUI/res/values-mn/strings.xml +++ b/packages/SystemUI/res/values-mn/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Царайгаар түгжээ тайлахыг тохируулж чадсангүй. Дахин оролдохын тулд Тохиргоо руу очно уу."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Хурууны хээ мэдрэгчид хүрэх"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Үргэлжлүүлэхийн тулд түгжээг тайлах дүрс тэмдгийг дарна уу"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"Царайг таньсангүй. Оронд нь хурууны хээ ашигла."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"Царайг таньсангүй"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Оронд нь хурууны хээ ашиглах"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"Царайгаар түгжээ тайлах боломжгүй"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth холбогдсон."</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Цэнэглэж байна • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>-н дараа дүүрнэ"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Нийтийн практик хичээлийг эхлүүлэхийн тулд зүүн тийш шударна уу"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Виджет засварлагчийг нээх"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Өөрчлөх"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Хаах"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Энэ орон зайд виджетүүдээ нэмэх, хасах болон дахин эрэмбэлэх"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Илүү олон виджет нэмэх"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Виджетүүдийг өөрчлөхийн тулд удаан дарна уу"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"Хасах"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Виджет нэмэх"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Болсон"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"Bluetooth-г асаах уу?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"Компьютерийн гараа таблетад холбохын тулд эхлээд Bluetooth-г асаана уу."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Асаах"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Тэжээлийн мэдэгдлийн удирдлага"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Асаалттай - Царайнд суурилсан"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"Тэжээлийн мэдэгдлийн удирдлагын тусламжтайгаар та апп-н мэдэгдэлд 0-5 хүртэлх ач холбогдлын түвшин тогтоох боломжтой. \n\n"<b>"5-р түвшин"</b>" \n- Мэдэгдлийн жагсаалтын хамгийн дээр харуулна \n- Бүтэн дэлгэцэд саад болно \n- Дэлгэцэд тогтмол гарч ирнэ \n\n"<b>"4-р түвшин"</b>" \n- Бүтэн дэлгэцэд саад болохоос сэргийлнэ \n- Дэлгэцэд тогтмол гарч ирнэ \n\n"<b>"3-р түвшин"</b>" \n- Бүтэн дэлгэцэд саад болохоос сэргийлнэ \n- Дэлгэцэд хэзээ ч гарч ирэхгүй \n\n"<b>"2-р түвшин"</b>" \n- Бүтэн дэлгэцэд саад болохоос сэргийлнэ \n- Дэлгэцэд хэзээ ч гарч ирэхгүй \n- Дуу болон чичиргээ хэзээ ч гаргахгүй \n\n"<b>"1-р түвшин"</b>" \n- Бүтэн дэлгэцэд саад болохоос сэргийлнэ \n- Дэлгэцэд хэзээ ч гарч ирэхгүй \n- Дуу болон чичиргээ хэзээ ч гаргахгүй \n- Түгжигдсэн дэлгэц болон статусын самбараас нууна \n- Мэдэгдлийн жагсаалтын доор харуулна \n\n"<b>"0-р түвшин"</b>" \n- Энэ апп-н бүх мэдэгдлийг блоклоно"</string> <string name="inline_done_button" msgid="6043094985588909584">"Болсон"</string> <string name="inline_ok_button" msgid="603075490581280343">"Ашиглах"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Мэдэгдлийг унтраах"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"Тохируулга"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"Хадгалах сан"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"Заавар"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"Хандалт"</string> <string name="instant_apps" msgid="8337185853050247304">"Шуурхай апп"</string> <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g>-г ажиллуулж байна"</string> <string name="instant_apps_message" msgid="6112428971833011754">"Аппыг суулгахгүйгээр нээсэн."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Хандалтын онцлогуудыг нээхийн тулд товшино уу. Энэ товчлуурыг Тохиргоо хэсэгт өөрчилж эсвэл солиорой.\n\n"<annotation id="link">"Тохиргоог харах"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Үүнийг түр нуухын тулд товчлуурыг зах руу зөөнө үү"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Болих"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"Хандалтын товчлуурыг нуусан"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Хандалтын товчлуурыг харуулахын тулд товшино уу"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g>-н товчлолыг хассан"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# товчлолыг хассан}other{# товчлолыг хассан}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Зүүн дээш зөөх"</string> diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml index 1a19c6b1ab27..58ceb7936ea1 100644 --- a/packages/SystemUI/res/values-mr/strings.xml +++ b/packages/SystemUI/res/values-mr/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"फेस अनलॉक सेट करता आले नाही. सेटिंग्ज वर जा आणि पुन्हा प्रयत्न करा."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"फिंगरप्रिंट सेन्सरला स्पर्श करा"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"पुढे सुरू ठेवण्यासाठी, अनलॉक करा चा आयकन प्रेस करा"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"चेहरा ओळखता आला नाही. त्याऐवजी फिंगरप्रिंट वापरा."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"चेहरा ओळखता आला नाही"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"त्याऐवजी फिंगरप्रिंट वापरा"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"फेस अनलॉक उपलब्ध नाही"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"ब्लूटूथ कनेक्ट केले."</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • चार्ज होत आहे • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> मध्ये पूर्ण होईल"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"सामुदायिक ट्यूटोरियल सुरू करण्यासाठी डावीकडे स्वाइप करा"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"विजेट संपादक उघडा"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"कस्टमाइझ करा"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"डिसमिस करा"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"या स्पेसमध्ये तुमची विजेट जोडा, काढून टाका आणि पुन्हा क्रमाने लावा"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"आणखी विजेट जोडा"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"विजेट कस्टमाइझ करण्यासाठी प्रेस करून ठेवा"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"काढून टाका"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"विजेट जोडा"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"पूर्ण झाले"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"ब्लूटूथ सुरू करायचे?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"तुमचा कीबोर्ड तुमच्या टॅबलेटसह कनेक्ट करण्यासाठी, तुम्ही प्रथम ब्लूटूथ सुरू करणे आवश्यक आहे."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"सुरू करा"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"पॉवर सूचना नियंत्रणे"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"सुरू - चेहऱ्यावर आधारित"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"पॉवर सूचना नियंत्रणांच्या साहाय्याने तुम्ही अॅप सूचनांसाठी 0 ते 5 असे महत्त्व स्तर सेट करू शकता. \n\n"<b>"स्तर 5"</b>" \n- सूचना सूचीच्या शीर्षस्थानी दाखवा \n- फुल स्क्रीन व्यत्ययास अनुमती द्या \n- नेहमी डोकावून पहा \n\n"<b>"स्तर 4"</b>\n" - फुल स्क्रीन व्यत्ययास प्रतिबंधित करा \n- नेहमी डोकावून पहा \n\n"<b>"स्तर 3"</b>" \n- फुल स्क्रीन व्यत्ययास प्रतिबंधित करा \n- कधीही डोकावून पाहू नका \n\n"<b>"स्तर 2"</b>" \n- फुल स्क्रीन व्यत्ययास प्रतिबंधित करा \n- कधीही डोकावून पाहू नका \n- कधीही ध्वनी किंवा व्हायब्रेट करू नका \n\n"<b>"स्तर 1"</b>\n"- फुल स्क्रीन व्यत्ययास प्रतिबंधित करा \n- कधीही डोकावून पाहू नका \n- कधीही ध्वनी किंवा व्हायब्रेट करू नका \n- लॉक स्क्रीन आणि स्टेटस बार मधून लपवा \n- सूचना सूचीच्या तळाशी दर्शवा \n\n"<b>"स्तर 0"</b>" \n- अॅपमधील सर्व सूचना ब्लॉक करा"</string> <string name="inline_done_button" msgid="6043094985588909584">"पूर्ण झाले"</string> <string name="inline_ok_button" msgid="603075490581280343">"लागू करा"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"सूचना बंद करा"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"सेटअप"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"स्टोरेज"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"सूचना"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"अॅक्सेसिबिलिटी"</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> रन होत आहे"</string> <string name="instant_apps_message" msgid="6112428971833011754">"इंस्टॉल केल्याशिवाय अॅप उघडले."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"अॅक्सेसिबिलिटी वैशिष्ट्ये उघडण्यासाठी, टॅप करा. सेटिंग्जमध्ये हे बटण कस्टमाइझ करा किंवा बदला.\n\n"<annotation id="link">"सेटिंग्ज पहा"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"बटण तात्पुरते लपवण्यासाठी ते कोपर्यामध्ये हलवा"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"पहिल्यासारखे करा"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"अॅक्सेसिबिलिटी बटण लपवलेले आहे"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"अॅक्सेसिबिलिटी बटण दाखवण्यासाठी टॅप करा"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> शॉर्टकट काढून टाकला"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# शॉर्टकट काढून टाकला}other{# शॉर्टकट काढून टाकले}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"वर डावीकडे हलवा"</string> diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml index 3bdb1841ce00..04e017011037 100644 --- a/packages/SystemUI/res/values-ms/strings.xml +++ b/packages/SystemUI/res/values-ms/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Tidak dapat menyediakan buka kunci wajah. Akses Tetapan untuk mencuba lagi."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Sentuh penderia cap jari"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Tekan ikon buka kunci untuk meneruskan proses"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"Wajah tidak dikenali. Gunakan cap jari."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"Wajah tidak dikenali"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Gunakan cap jari"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"Buka Kunci Wajah tidak tersedia"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth disambungkan."</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Mengecas • Penuh dalam masa <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Leret ke kiri untuk memulakan tutorial umum"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Buka editor widget"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Sesuaikan"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Ketepikan"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Tambahkan, alih keluar dan susun semula widget anda dalam ruang ini"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Tambahkan lagi widget"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Tekan lama untuk menyesuaikan widget"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"Alih keluar"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Tambahkan widget"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Selesai"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"Hidupkan Bluetooth?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"Untuk menyambungkan papan kekunci anda dengan tablet, anda perlu menghidupkan Bluetooth terlebih dahulu."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Hidupkan"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Kawalan pemberitahuan berkuasa"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Hidup - Berasaskan wajah"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"Dengan kawalan pemberitahuan berkuasa, anda boleh menetapkan tahap kepentingan dari 0 hingga 5 untuk pemberitahuan apl. \n\n"<b>"Tahap 5"</b>" \n- Tunjukkan pada bahagian atas senarai pemberitahuan \n- Benarkan gangguan skrin penuh \n- Sentiasa intai \n\n"<b>"Tahap 4"</b>" \n- Halang gangguan skrin penuh \n- Sentiasa intai \n\n"<b>"Tahap 3"</b>" \n- Halang gangguan skrin penuh \n- Jangan intai \n\n"<b>"Tahap 2"</b>" \n- Halang gangguan skrin penuh \n- Jangan intai \n- Jangan berbunyi dan bergetar \n\n"<b>"Tahap 1"</b>" \n- Halang gangguan skrin penuh \n- Jangan intai \n- Jangan berbunyi atau bergetar \n- Sembunyikan daripada skrin kunci dan bar status \n- Tunjukkan di bahagian bawah senarai pemberitahuan \n\n"<b>"Tahap 0"</b>" \n- Sekat semua pemberitahuan daripada apl"</string> <string name="inline_done_button" msgid="6043094985588909584">"Selesai"</string> <string name="inline_ok_button" msgid="603075490581280343">"Guna"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Matikan pemberitahuan"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"Persediaan"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"Storan"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"Pembayang"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"Kebolehaksesan"</string> <string name="instant_apps" msgid="8337185853050247304">"Apl Segera"</string> <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> sedang berjalan"</string> <string name="instant_apps_message" msgid="6112428971833011754">"Apl dibuka tanpa dipasang."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Ketik untuk membuka ciri kebolehaksesan. Sesuaikan/gantikan butang ini dalam Tetapan.\n\n"<annotation id="link">"Lihat tetapan"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Gerakkan butang ke tepi untuk disembunyikan buat sementara waktu"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Buat asal"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"Butang kebolehaksesan disembunyikan"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Ketik untuk memaparkan butang kebolehaksesan"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Pintasan <xliff:g id="FEATURE_NAME">%s</xliff:g> dialih keluar"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# pintasan dialih keluar}other{# pintasan dialih keluar}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Alihkan ke atas sebelah kiri"</string> diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml index af2d583e6a47..5b7fa6d1245c 100644 --- a/packages/SystemUI/res/values-my/strings.xml +++ b/packages/SystemUI/res/values-my/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"မျက်နှာပြ လော့ခ်ဖွင့်ခြင်းကို စနစ်ထည့်သွင်း၍မရပါ။ ဆက်တင်များသို့သွားပြီး ထပ်စမ်းကြည့်ပါ။"</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"လက်ဗွေအာရုံခံကိရိယာကို တို့ပါ"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"ရှေ့ဆက်ရန် လော့ခ်ဖွင့်သင်္ကေတကို နှိပ်ပါ"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"မျက်နှာကို မသိရှိပါ။ လက်ဗွေကို အစားထိုးသုံးပါ။"</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"မျက်နှာကို မသိရှိပါ"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"လက်ဗွေကို အစားထိုးသုံးပါ"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"မျက်နှာပြ လော့ခ်ဖွင့်ခြင်း မရနိုင်ပါ"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"ဘလူးတုသ်ချိတ်ဆက်ထားမှု"</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • အားသွင်းနေသည် • အားပြည့်ရန် <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> လိုသည်"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"အများသုံးရှင်းလင်းပို့ချချက် စတင်ရန် ဘယ်သို့ပွတ်ဆွဲပါ"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"ဝိဂျက်တည်းဖြတ်စနစ် ဖွင့်ရန်"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"စိတ်ကြိုက်လုပ်ရန်"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"ပယ်ရန်"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"ဤနေရာတွင် သင့်ဝိဂျက်များကို ထည့်ရန်၊ ဖယ်ရှားရန်၊ ပြန်စီရန်"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"နောက်ထပ်ဝိဂျက်များ ထည့်ရန်"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"ဝိဂျက်များ စိတ်ကြိုက်လုပ်ရန် ကြာကြာနှိပ်ထားပါ"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"ဖယ်ရှားရန်"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"ဝိဂျက်ထည့်ရန်"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"ပြီးပြီ"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"ဘလူးတုသ် ဖွင့်ရမလား။"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"ကီးဘုတ်ကို တပ်ဘလက်နှင့် ချိတ်ဆက်ရန်၊ ပမထဦးစွာ ဘလူးတုသ်ကို ဖွင့်ပါ။"</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"ဖွင့်ပါ"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"ပါဝါအကြောင်းကြားချက် ထိန်းချုပ်မှုများ"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"ဖွင့် - မျက်နှာအခြေခံ"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"ပါဝါအကြောင်းကြားချက် ထိန်းချုပ်မှုများကိုအသုံးပြုပြီး အက်ပ်တစ်ခု၏ အကြောင်းကြားချက် အရေးပါမှု ၀ မှ ၅ အထိသတ်မှတ်ပေးနိုင်သည်။ \n\n"<b>"အဆင့် ၅"</b>" \n- အကြောင်းကြားချက်စာရင်း၏ ထိပ်ဆုံးတွင် ပြသည် \n- မျက်နှာပြင်အပြည့် ကြားဖြတ်ဖော်ပြခြင်းကို ခွင့်ပြုသည် \n- အမြဲတမ်း ခေတ္တပြပါမည် \n\n"<b>"အဆင့် ၄"</b>" \n- မျက်နှာပြင်အပြည့် ကြားဖြတ်ဖော်ပြခြင်း မရှိစေရန် ကာကွယ်ပေးသည် \n- အမြဲတမ်း ခေတ္တပြပါမည် \n\n"<b>"အဆင့် ၃"</b>" \n- မျက်နှာပြင်အပြည့် ကြားဖြတ်ဖော်ပြခြင်း မရှိစေရန် ကာကွယ်ပေးသည် \n- ဘယ်တော့မှ ခေတ္တပြခြင်း မရှိပါ \n\n"<b>"အဆင့် ၂"</b>" \n- မျက်နှာပြင်အပြည့် ကြားဖြတ်ဖော်ပြခြင်း မရှိစေရန် ကာကွယ်ပေးသည် \n- ဘယ်တော့မှ ခေတ္တပြခြင်း မရှိပါ \n- အသံမြည်ခြင်းနှင့် တုန်ခါခြင်းများ ဘယ်တော့မှ မပြုလုပ်ပါ \n\n"<b>"အဆင့် ၁"</b>" \n- မျက်နှာပြင်အပြည့် ကြားဖြတ်ဖော်ပြခြင်း မရှိစေရန် ကာကွယ်ပေးသည် \n- ဘယ်တော့မှ ခေတ္တပြခြင်း မရှိပါ \n- အသံမြည်ခြင်းနှင့် တုန်ခါခြင်းများ ဘယ်တော့မှ မပြုလုပ်ပါ \n- လော့ခ်ချထားသည့် မျက်နှာပြင်နှင့် အခြေအနေဘားတန်းတို့တွင် မပြပါ \n- အကြောင်းကြားချက်စာရင်း အောက်ဆုံးတွင်ပြသည် \n\n"<b>"အဆင့် ၀"</b>" \n- အက်ပ်မှ အကြောင်းကြားချက်များ အားလုံးကို ပိတ်ဆို့သည်"</string> <string name="inline_done_button" msgid="6043094985588909584">"ပြီးပြီ"</string> <string name="inline_ok_button" msgid="603075490581280343">"အသုံးပြုရန်"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"အကြောင်းကြားချက်များ ပိတ်ရန်"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"စနစ်ထည့်ရန်"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"သိုလှောင်ခန်း"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"အရိပ်အမြွက်များ"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"အများသုံးနိုင်မှု"</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> လုပ်ဆောင်နေသည်"</string> <string name="instant_apps_message" msgid="6112428971833011754">"အက်ပ်ကိုမထည့်သွင်းဘဲ ဖွင့်ထားသည်။"</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"အများသုံးစွဲနိုင်မှုဆိုင်ရာ ဝန်ဆောင်မှုများ ဖွင့်ရန် တို့ပါ။ ဆက်တင်များတွင် ဤခလုတ်ကို စိတ်ကြိုက်ပြင်ပါ (သို့) လဲပါ။\n\n"<annotation id="link">"ဆက်တင်များ ကြည့်ရန်"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"ခလုတ်ကို ယာယီဝှက်ရန် အစွန်းသို့ရွှေ့ပါ"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"နောက်ပြန်ရန်"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"အများသုံးနိုင်မှုခလုတ်ကို ဝှက်ထားသည်"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"အများသုံးနိုင်မှုခလုတ်ပြရန် တို့ပါ"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> ဖြတ်လမ်းလင့်ခ် ဖယ်ရှားထားသည်"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{ဖြတ်လမ်းလင့်ခ် # ခု ဖယ်ရှားထားသည်}other{ဖြတ်လမ်းလင့်ခ် # ခု ဖယ်ရှားထားသည်}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"ဘယ်ဘက်ထိပ်သို့ ရွှေ့ရန်"</string> diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml index 89f58d7d781b..1dd377e441d8 100644 --- a/packages/SystemUI/res/values-nb/strings.xml +++ b/packages/SystemUI/res/values-nb/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Kunne ikke konfigurere ansiktslåsen. Gå til innstillingene for å prøve på nytt."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Trykk på fingeravtrykkssensoren"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Trykk på lås opp-ikonet for å fortsette"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"Ansiktet ble ikke gjenkjent. Bruk fingeravtrykk."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"Ansikt ikke gjenkjent"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Bruk fingeravtrykk"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"Ansiktslås er utilgjengelig"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth er tilkoblet."</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Lader • Fulladet om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Sveip til venstre for å starte fellesveiledningen"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Åpne redigeringsverktøyet for moduler"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Tilpass"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Lukk"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Legg til, fjern og omorganiser modulene i dette området"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Legg til flere moduler"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Trykk lenge for å tilpasse modulene"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"Fjern"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Legg til modul"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Ferdig"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"Vil du slå på Bluetooth?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"For å koble tastaturet til nettbrettet ditt må du først slå på Bluetooth."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Slå på"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Effektive varselinnstillinger"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"På – ansiktsbasert"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"Med effektive varselinnstillinger kan du angi viktighetsnivåer fra 0 til 5 for appvarsler. \n\n"<b>"Nivå 5"</b>" \n– Vis øverst på varsellisten \n– Tillat forstyrrelser ved fullskjermmodus \n– Vis alltid raskt \n\n"<b>"Nivå 4"</b>" \n– Forhindre forstyrrelser ved fullskjermmodus \n– Vis alltid raskt \n\n"<b>"Nivå 3"</b>" \n– Forhindre forstyrrelser ved fullskjermmodus \n– Vis aldri raskt \n\n"<b>"Nivå 2"</b>" \n– Forhindre forstyrrelser ved fullskjermmodus \n– Vis aldri fort \n– Tillat aldri lyder eller vibrering \n\n"<b>"Nivå 1"</b>" \n– Forhindre forstyrrelser ved fullskjermmodus \n– Vis aldri raskt \n– Tillat aldri lyder eller vibrering \n– Skjul fra låseskjermen og statusfeltet \n– Vis nederst på varsellisten \n\n"<b>"Nivå 0"</b>" \n– Blokkér alle varsler fra appen"</string> <string name="inline_done_button" msgid="6043094985588909584">"Ferdig"</string> <string name="inline_ok_button" msgid="603075490581280343">"Bruk"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Slå av varsler"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"Konfigurering"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"Lagring"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"Hint"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"Tilgjengelighet"</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> kjører"</string> <string name="instant_apps_message" msgid="6112428971833011754">"Appen ble åpnet uten at den ble installert."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Trykk for å åpne tilgj.funksjoner. Tilpass eller bytt knappen i Innstillinger.\n\n"<annotation id="link">"Se innstillingene"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Flytt knappen til kanten for å skjule den midlertidig"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Angre"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"Tilgjengelighet-knappen er skjult"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Trykk for å vise Tilgjengelighet-knappen"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g>-snarveien er fjernet"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# snarvei er fjernet}other{# snarveier er fjernet}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Flytt til øverst til venstre"</string> diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml index 51d50443cfc8..58baedea8ea5 100644 --- a/packages/SystemUI/res/values-ne/strings.xml +++ b/packages/SystemUI/res/values-ne/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"फेस अनलक सेटअप गर्न सकिएन। फेरि प्रयास गर्न सेटिङमा जानुहोस्।"</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"फिंगरप्रिन्ट सेन्सरमा छुनुहोस्"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"जारी राख्न अनलक आइकनमा थिच्नुहोस्"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"अनुहार पहिचान गर्न सकिएन। बरु फिंगरप्रिन्ट प्रयोग गर्नुहोस्।"</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"अनुहार पहिचान गर्न सकिएन"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"बरु फिंगरप्रिन्ट प्रयोग गर्नुहोस्"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"फेस अनलक उपलब्ध छैन"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"ब्लुटुथ जडान भयो।"</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • चार्ज हुँदै छ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> मा फुल चार्ज हुने छ"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"कम्युनल ट्युटोरियल सुरु गर्न बायाँतिर स्वाइप गर्नुहोस्"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"विजेट एडिटर खोल्नुहोस्"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"कस्टमाइज गर्नुहोस्"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"खारेज गर्नुहोस्"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"यो स्पेसमा आफ्ना विजेटहरू हाल्नुहोस्, हटाउनुहोस् र तिनका क्रम फेरि मिलाउनुहोस्"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"थप विजेटहरू हाल्नुहोस्"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"विजेटहरू कस्टमाइज गर्न केही बेरसम्म थिच्नुहोस्"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"हटाउनुहोस्"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"विजेट हाल्नुहोस्"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"पूरा भयो"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"ब्लुटुथ सक्रिय पार्ने हो?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"आफ्नो ट्याब्लेटसँग किबोर्ड जोड्न, पहिले तपाईँले ब्लुटुथ सक्रिय गर्नुपर्छ।"</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"सक्रिय पार्नुहोस्"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"सशक्त सूचना नियन्त्रण"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"अन छ - अनुहारमा आधारित"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"सशक्त सूचना नियन्त्रणहरू मार्फत तपाईं अनुप्रयाेगका सूचनाहरूका लागि ० देखि ५ सम्मको महत्व सम्बन्धी स्तर सेट गर्न सक्नुहुन्छ। \n\n"<b>"स्तर ५"</b>" \n- सूचनाको सूचीको माथिल्लो भागमा देखाउने \n- पूर्ण स्क्रिनमा अवरोधका लागि अनुमति दिने \n- सधैँ चियाउने \n\n"<b>"स्तर ४"</b>" \n- पूर्ण स्क्रिनमा अवरोधलाई रोक्ने \n- सधैँ चियाउने \n\n"<b>"स्तर ३"</b>" \n- पूर्ण स्क्रिनमा अवरोधलाई रोक्ने \n- कहिल्यै नचियाउने \n\n"<b>"स्तर २"</b>" \n- पूर्ण स्क्रिनमा अवरोधलाई रोक्ने \n- कहिल्यै नचियाउने \n- कहिल्यै पनि आवाज ननिकाल्ने र कम्पन नगर्ने \n\n"<b>"स्तर १"</b>" \n- पूर्ण स्क्रिनमा अवरोध रोक्ने \n- कहिल्यै नचियाउने \n- कहिल्यै पनि आवाज ननिकाल्ने वा कम्पन नगर्ने \n- लक स्क्रिन र वस्तुस्थिति पट्टीबाट लुकाउने \n- सूचनाको सूचीको तल्लो भागमा देखाउने \n\n"<b>"स्तर ०"</b>" \n- एपका सबै सूचनाहरूलाई रोक्ने"</string> <string name="inline_done_button" msgid="6043094985588909584">"सम्पन्न भयो"</string> <string name="inline_ok_button" msgid="603075490581280343">"लागू गर्नुहोस्"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"सूचनाहरू अफ गर्नुहोस्"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"सेटअप गर्नुहोस्"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"भण्डारण"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"सङ्केतहरू"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"एक्सेसिबिलिटी"</string> <string name="instant_apps" msgid="8337185853050247304">"तात्कालिक एपहरू"</string> <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> चलिरहेको छ"</string> <string name="instant_apps_message" msgid="6112428971833011754">"स्थापना नगरिकनै एप खोलियो।"</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"सर्वसुलभता कायम गर्ने सुविधा खोल्न ट्याप गर्नुहोस्। सेटिङमा गई यो बटन कस्टमाइज गर्नुहोस् वा बदल्नुहोस्।\n\n"<annotation id="link">"सेटिङ हेर्नुहोस्"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"यो बटन केही बेर नदेखिने पार्न किनारातिर सार्नुहोस्"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"अन्डू गर्नुहोस्"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"एक्सेसिबिलिटी बटन लुकाइएको छ"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"एक्सेसिबिलिटी बटन देखाउन ट्याप गर्नुहोस्"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> सर्टकट हटाइएको छ"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# सर्टकट हटाइएको छ}other{# वटा सर्टकट हटाइएका छन्}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"सिरानको बायाँतिर सार्नुहोस्"</string> diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml index 90551954caee..a882a28e46dc 100644 --- a/packages/SystemUI/res/values-nl/strings.xml +++ b/packages/SystemUI/res/values-nl/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Kan ontgrendelen via gezichtsherkenning niet instellen. Ga naar Instellingen om het opnieuw te proberen."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Raak de vingerafdruksensor aan"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Druk op het ontgrendelicoon om door te gaan"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"Gezicht niet herkend. Gebruik je vingerafdruk."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"Gezicht niet herkend"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Vingerafdruk gebruiken"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"Ontgrendelen via gezichtsherkenning niet beschikbaar"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth-verbinding ingesteld."</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Opladen • Vol over <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Swipe naar links om de communitytutorial te starten"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"De widget-editor openen"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Aanpassen"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Sluiten"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Je widgets aan deze ruimte toevoegen, eruit verwijderen of opnieuw ordenen"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Meer widgets toevoegen"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Houd lang ingedrukt om widgets aan te passen"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"Verwijderen"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Widget toevoegen"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Klaar"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"Bluetooth aanzetten?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"Als je je toetsenbord wilt verbinden met je tablet, moet je eerst Bluetooth aanzetten."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Aanzetten"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Beheeropties voor meldingen met betrekking tot stroomverbruik"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Aan: op basis van gezicht"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"Met beheeropties voor meldingen met betrekking tot stroomverbruik kun je een belangrijkheidsniveau van 0 tot 5 instellen voor de meldingen van een app. \n\n"<b>"Niveau 5"</b>" \n- Bovenaan de lijst met meldingen tonen \n- Onderbreking op volledig scherm toestaan \n- Altijd korte weergave \n\n"<b>"Niveau 4"</b>" \n- Geen onderbreking op volledig scherm \n- Altijd korte weergave \n\n"<b>"Niveau 3"</b>" \n- Geen onderbreking op volledig scherm \n- Nooit korte weergave \n\n"<b>"Niveau 2"</b>" \n- Geen onderbreking op volledig scherm \n- Nooit korte weergave \n- Nooit geluid laten horen of trillen \n\n"<b>"Niveau 1"</b>" \n- Geen onderbreking op volledig scherm \n- Nooit korte weergave \n- Nooit geluid laten horen of trillen \n- Verbergen op vergrendelscherm en statusbalk \n- Onderaan de lijst met meldingen tonen \n\n"<b>"Niveau 0"</b>" \n- Alle meldingen van de app blokkeren"</string> <string name="inline_done_button" msgid="6043094985588909584">"Klaar"</string> <string name="inline_ok_button" msgid="603075490581280343">"Toepassen"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Meldingen uitzetten"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"Instellen"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"Opslag"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"Hints"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"Toegankelijkheid"</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> actief"</string> <string name="instant_apps_message" msgid="6112428971833011754">"App geopend zonder dat deze is geïnstalleerd."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Tik voor toegankelijkheidsfuncties. Wijzig of vervang deze knop via Instellingen.\n\n"<annotation id="link">"Naar Instellingen"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Knop naar de rand verplaatsen om deze tijdelijk te verbergen"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Ongedaan maken"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"Knop Toegankelijkheid verborgen"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Tik om de knop Toegankelijkheid te tonen"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Snelkoppeling voor <xliff:g id="FEATURE_NAME">%s</xliff:g> verwijderd"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# snelkoppeling verwijderd}other{# snelkoppelingen verwijderd}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Naar linksboven verplaatsen"</string> diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml index 9a31fc0f5109..59145d429045 100644 --- a/packages/SystemUI/res/values-or/strings.xml +++ b/packages/SystemUI/res/values-or/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"ଫେସ ଅନଲକ ସେଟ ଅପ କରାଯାଇପାରିଲା ନାହିଁ। ପୁଣି ଚେଷ୍ଟା କରିବା ପାଇଁ ସେଟିଂସକୁ ଯାଆନ୍ତୁ।"</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"ଟିପଚିହ୍ନ ସେନସର୍କୁ ଛୁଅଁନ୍ତୁ"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"ଜାରି ରଖିବାକୁ ଅନଲକ ଆଇକନ ଦବାନ୍ତୁ"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"ଫେସ ଚିହ୍ନଟ କରାଯାଇନାହିଁ। ଟିପଚିହ୍ନ ବ୍ୟବହାର କରନ୍ତୁ।"</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"ଫେସ ଚିହ୍ନଟ କରାଯାଇନାହିଁ"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"ଟିପଚିହ୍ନ ବ୍ୟବହାର କରନ୍ତୁ"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"ଫେସ ଅନଲକ ଉପଲବ୍ଧ ନାହିଁ"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"ବ୍ଲୁଟୂଥ୍ ସଂଯୋଗ କରାଯାଇଛି।"</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ଚାର୍ଜ ହେଉଛି • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>ରେ ସମ୍ପୂର୍ଣ୍ଣ ହେବ"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"କମ୍ୟୁନାଲ ଟ୍ୟୁଟୋରିଆଲ ଆରମ୍ଭ କରିବା ପାଇଁ ବାମକୁ ସ୍ୱାଇପ କରନ୍ତୁ"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"ୱିଜେଟ ଏଡିଟର ଖୋଲନ୍ତୁ"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"କଷ୍ଟମାଇଜ କରନ୍ତୁ"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"ଖାରଜ କରନ୍ତୁ"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"ଏହି ସ୍ପେସରେ ଆପଣଙ୍କ ୱିଜେଟଗୁଡ଼ିକୁ ଯୋଗ କରନ୍ତୁ, କାଢ଼ି ଦିଅନ୍ତୁ ଏବଂ ରିଅର୍ଡର କରନ୍ତୁ"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"ଅଧିକ ୱିଜେଟ ଯୋଗ କରନ୍ତୁ"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"ୱିଜେଟଗୁଡ଼ିକୁ କଷ୍ଟମାଇଜ କରିବା ପାଇଁ ଅଧିକ ସମୟ ଦବାନ୍ତୁ"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"କାଢ଼ି ଦିଅନ୍ତୁ"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"ୱିଜେଟ ଯୋଗ କରନ୍ତୁ"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"ହୋଇଗଲା"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"ବ୍ଲୁଟୂଥ୍ ଚାଲୁ କରିବେ?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"ଆପଣଙ୍କ ଟାବଲେଟ୍ରେ କୀ’ବୋର୍ଡ ସଂଯୋଗ କରିବା ପାଇଁ ଆପଣଙ୍କୁ ପ୍ରଥମେ ବ୍ଲୁଟୂଥ୍ ଅନ୍ କରିବାକୁ ହେବ।"</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"ଚାଲୁ କରନ୍ତୁ"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"ପାୱାର୍ ବିଜ୍ଞପ୍ତି କଣ୍ଟ୍ରୋଲ୍"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"ଚାଲୁ ଅଛି - ଫେସ-ଆଧାରିତ"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"ପାୱାର୍ ବିଜ୍ଞପ୍ତି କଣ୍ଟ୍ରୋଲ୍ରେ, ଆପଣ ଏକ ଆପ୍ ବିଜ୍ଞପ୍ତି ପାଇଁ 0 ରୁ 5 ଗୁରୁତ୍ୱ ସ୍ତର ସେଟ୍ କରିହେବେ। \n\n"<b>"ସ୍ତର 5"</b>" \n- ବିଜ୍ଞପ୍ତି ତାଲିକାର ଶୀର୍ଷରେ ଦେଖାନ୍ତୁ \n- ପୂର୍ଣ୍ଣ ସ୍କ୍ରୀନରେ ବାଧା ଦେବାକୁ ଅନୁମତି ଦିଅନ୍ତୁ \n- ସର୍ବଦା ପିକ୍ କରନ୍ତୁ \n\n"<b>"ସ୍ତର 4"</b>" \n- ପୂର୍ଣ୍ଣ ସ୍କ୍ରୀନରେ ବାଧା ଦେବା ବ୍ଲକ୍ କରନ୍ତୁ \n- ସର୍ବଦା ପିକ୍ କରନ୍ତୁ \n\n"<b>"ସ୍ତର 3"</b>" \n- ପୂର୍ଣ୍ଣ ସ୍କ୍ରୀନରେ ବାଧା ଦେବା ବ୍ଲକ୍ କରନ୍ତୁ \n- କଦାପି ପିକ୍ କରନ୍ତୁ ନାହିଁ \n\n"<b>"ସ୍ତର 2"</b>" \n- ପୂର୍ଣ୍ଣ ସ୍କ୍ରୀନରେ ବାଧା ଦେବା ବ୍ଲକ୍ କରନ୍ତୁ \n- କଦାପି ପିକ୍ କରନ୍ତୁ ନାହିଁ \n- କଦାପି ସାଉଣ୍ଡ ଓ ଭାଇବ୍ରେଟ୍ କରନ୍ତୁ ନାହିଁ \n\n"<b>"ସ୍ତର 1"</b>" \n- ପୂର୍ଣ୍ଣ ସ୍କ୍ରୀନରେ ବାଧା ଦେବା ବ୍ଲକ୍ କରନ୍ତୁ \n- କଦାପି ପିକ୍ କରନ୍ତୁ ନାହିଁ \n- କଦାପି ସାଉଣ୍ଡ ଓ ଭାଇବ୍ରେଟ୍ କରନ୍ତୁ ନାହିଁ \n- ଲକ୍ ସ୍କ୍ରୀନ୍ ଓ ଷ୍ଟାଟସ୍ ବାର୍ରୁ ଲୁଚାନ୍ତୁ \n- ବିଜ୍ଞପ୍ତି ତାଲିକାର ନିମ୍ନରେ ଦେଖାନ୍ତୁ \n\n"<b>"ସ୍ତର 0"</b>" \n- ଆପରୁ ସମସ୍ତ ବିଜ୍ଞପ୍ତି ବ୍ଲକ୍ କରନ୍ତୁ"</string> <string name="inline_done_button" msgid="6043094985588909584">"ହୋଇଗଲା"</string> <string name="inline_ok_button" msgid="603075490581280343">"ଲାଗୁ କରନ୍ତୁ"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"ବିଜ୍ଞପ୍ତି ବନ୍ଦ କରନ୍ତୁ"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"ସେଟଅପ"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"ଷ୍ଟୋରେଜ"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"ହିଣ୍ଟ"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"ଆକ୍ସେସିବିଲିଟୀ"</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> ଚାଲୁଛି"</string> <string name="instant_apps_message" msgid="6112428971833011754">"ଇନ୍ଷ୍ଟଲ୍ ନହୋଇ ଆପ୍ ଖୋଲିଛି।"</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"ଆକ୍ସେସିବିଲିଟୀ ଫିଚର ଖୋଲିବାକୁ ଟାପ କରନ୍ତୁ। ସେଟିଂସରେ ଏହି ବଟନକୁ କଷ୍ଟମାଇଜ କର କିମ୍ବା ବଦଳାଅ।\n\n"<annotation id="link">"ସେଟିଂସ ଦେଖନ୍ତୁ"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"ବଟନକୁ ଅସ୍ଥାୟୀ ଭାବେ ଲୁଚାଇବା ପାଇଁ ଏହାକୁ ଗୋଟିଏ ଧାରକୁ ମୁଭ୍ କରନ୍ତୁ"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"ପୂର୍ବବତ୍ କରନ୍ତୁ"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"ଆକ୍ସେସିବିଲିଟୀ ବଟନକୁ ଲୁଚାଯାଇଛି"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"ଆକ୍ସେସିବିଲିଟୀ ବଟନ ଦେଖାଇବାକୁ ଟାପ କରନ୍ତୁ"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> ସର୍ଟକଟକୁ କାଢ଼ି ଦିଆଯାଇଛି"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{#ଟି ସର୍ଟକଟକୁ କାଢ଼ି ଦିଆଯାଇଛି}other{#ଟି ସର୍ଟକଟକୁ କାଢ଼ି ଦିଆଯାଇଛି}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"ଶୀର୍ଷ ବାମକୁ ମୁଭ୍ କରନ୍ତୁ"</string> diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml index bd71d5f73ebd..be69c1eab54e 100644 --- a/packages/SystemUI/res/values-pa/strings.xml +++ b/packages/SystemUI/res/values-pa/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"ਫ਼ੇਸ ਅਣਲਾਕ ਦਾ ਸੈੱਟਅੱਪ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰਨ ਲਈ ਸੈਟਿੰਗਾਂ \'ਤੇ ਜਾਓ।"</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਸੈਂਸਰ ਨੂੰ ਸਪੱਰਸ਼ ਕਰੋ"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"ਜਾਰੀ ਰੱਖਣ ਲਈ \'ਅਣਲਾਕ ਕਰੋ\' ਪ੍ਰਤੀਕ ਨੂੰ ਦਬਾਓ"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"ਚਿਹਰੇ ਦੀ ਪਛਾਣ ਨਹੀਂ ਹੋਈ। ਇਸਦੀ ਬਜਾਏ ਫਿੰਗਰਪ੍ਰਿੰਟ ਵਰਤੋ।"</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"ਚਿਹਰੇ ਦੀ ਪਛਾਣ ਨਹੀਂ ਹੋਈ"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"ਇਸਦੀ ਬਜਾਏ ਫਿੰਗਰਪ੍ਰਿੰਟ ਵਰਤੋ"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"ਫ਼ੇਸ ਅਣਲਾਕ ਉਪਲਬਧ ਨਹੀਂ ਹੈ"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth ਕਨੈਕਟ ਕੀਤੀ।"</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> ਵਿੱਚ ਪੂਰਾ ਚਾਰਜ ਹੋਵੇਗਾ"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"ਭਾਈਚਾਰਕ ਟਿਊਟੋਰੀਅਲ ਸ਼ੁਰੂ ਕਰਨ ਲਈ ਖੱਬੇ ਪਾਸੇ ਵੱਲ ਸਵਾਈਪ ਕਰੋ"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"ਵਿਜੇਟ ਸੰਪਾਦਕ ਖੋਲ੍ਹੋ"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"ਵਿਉਂਤਬੱਧ ਕਰੋ"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"ਖਾਰਜ ਕਰੋ"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"ਇਸ ਜਗ੍ਹਾ ਵਿੱਚ ਆਪਣੇ ਵਿਜੇਟ ਸ਼ਾਮਲ ਕਰੋ, ਹਟਾਓ ਅਤੇ ਮੁੜ-ਕ੍ਰਮਬੱਧ ਕਰੋ"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"ਹੋਰ ਵਿਜੇਟ ਸ਼ਾਮਲ ਕਰੋ"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"ਵਿਜੇਟਾਂ ਨੂੰ ਵਿਉਂਤਬੱਧ ਕਰਨ ਲਈ ਦਬਾਈ ਰੱਖੋ"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"ਹਟਾਓ"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"ਵਿਜੇਟ ਸ਼ਾਮਲ ਕਰੋ"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"ਹੋ ਗਿਆ"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"Bluetooth ਚਾਲੂ ਕਰੋ?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"ਆਪਣੇ ਟੈਬਲੈੱਟ ਨਾਲ ਆਪਣਾ ਕੀ-ਬੋਰਡ ਕਨੈਕਟ ਕਰਨ ਲਈ, ਤੁਹਾਨੂੰ ਪਹਿਲਾਂ ਬਲੂਟੁੱਥ ਚਾਲੂ ਕਰਨ ਦੀ ਲੋੜ ਹੈ।"</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"ਚਾਲੂ ਕਰੋ"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"ਪਾਵਰ ਸੂਚਨਾ ਕੰਟਰੋਲ"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"ਚਾਲੂ ਹੈ - ਚਿਹਰਾ-ਆਧਾਰਿਤ"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"ਪਾਵਰ ਸੂਚਨਾ ਕੰਟਰੋਲਾਂ ਨਾਲ, ਤੁਸੀਂ ਕਿਸੇ ਐਪ ਦੀਆਂ ਸੂਚਨਾਵਾਂ ਲਈ ਮਹੱਤਤਾ ਪੱਧਰ ਨੂੰ 0 ਤੋਂ 5 ਤੱਕ ਸੈੱਟ ਕਰ ਸਕਦੇ ਹੋ। \n\n"<b>"ਪੱਧਰ 5"</b>" \n- ਸੂਚਨਾ ਸੂਚੀ ਦੇ ਸਿਖਰ \'ਤੇ ਦਿਖਾਓ \n- ਪੂਰੀ ਸਕ੍ਰੀਨ ਰੁਕਾਵਟ ਦੀ ਆਗਿਆ ਦਿਓ \n- ਹਮੇਸ਼ਾਂ ਝਲਕ ਦਿਖਾਓ \n\n"<b>"ਪੱਧਰ 4"</b>" \n- ਪੂਰੀ ਸਕ੍ਰੀਨ ਰੁਕਾਵਟ ਨੂੰ ਰੋਕੋ \n- ਹਮੇਸ਼ਾਂ ਝਲਕ ਦਿਖਾਓ \n\n"<b>"ਪੱਧਰ 3"</b>" \n- ਪੂਰੀ ਸਕ੍ਰੀਨ ਰੁਕਾਵਟ ਨੂੰ ਰੋਕੋ \n- ਕਦੇ ਝਲਕ ਨਾ ਦਿਖਾਓ \n\n"<b>"ਪੱਧਰ 2"</b>" \n- ਪੂਰੀ ਸਕ੍ਰੀਨ ਰੁਕਾਵਟ ਨੂੰ ਰੋਕੋ \n- ਕਦੇ ਝਲਕ ਨਾ ਦਿਖਾਓ \n- ਕਦੇ ਵੀ ਧੁਨੀ ਜਾਂ ਥਰਥਰਾਹਟ ਨਾ ਕਰੋ \n\n"<b>"ਪੱਧਰ 1"</b>" \n- ਪੂਰੀ ਸਕ੍ਰੀਨ ਰੁਕਾਵਟ ਨੂੰ ਰੋਕੋ \n- ਕਦੇ ਝਲਕ ਨਾ ਦਿਖਾਓ \n- ਕਦੇ ਧੁਨੀ ਜਾਂ ਥਰਥਰਾਹਟ ਨਾ ਕਰੋ \n- ਲਾਕ ਸਕ੍ਰੀਨ ਅਤੇ ਸਥਿਤੀ ਪੱਟੀ ਤੋਂ ਲੁਕਾਓ \n- ਸੂਚਨਾ ਸੂਚੀ ਦੇ ਹੇਠਾਂ ਦਿਖਾਓ \n\n"<b>"ਪੱਧਰ 0"</b>" \n- ਐਪ ਤੋਂ ਸਾਰੀਆਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਬਲਾਕ ਕਰੋ"</string> <string name="inline_done_button" msgid="6043094985588909584">"ਹੋ ਗਿਆ"</string> <string name="inline_ok_button" msgid="603075490581280343">"ਲਾਗੂ ਕਰੋ"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"ਸੂਚਨਾਵਾਂ ਬੰਦ ਕਰੋ"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"ਸੈੱਟਅੱਪ ਕਰੋ"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"ਸਟੋਰੇਜ"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"ਸੰਕੇਤ"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"ਪਹੁੰਚਯੋਗਤਾ"</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> ਚੱਲ ਰਹੀ ਹੈ"</string> <string name="instant_apps_message" msgid="6112428971833011754">"ਸਥਾਪਤ ਕੀਤੇ ਬਿਨਾਂ ਐਪ ਖੋਲ੍ਹੀ ਗਈ।"</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"ਪਹੁੰਚਯੋਗਤਾ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਖੋਲ੍ਹਣ ਲਈ ਟੈਪ ਕਰੋ। ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਇਹ ਬਟਨ ਵਿਉਂਤਬੱਧ ਕਰੋ ਜਾਂ ਬਦਲੋ।\n\n"<annotation id="link">"ਸੈਟਿੰਗਾਂ ਦੇਖੋ"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"ਬਟਨ ਨੂੰ ਅਸਥਾਈ ਤੌਰ \'ਤੇ ਲੁਕਾਉਣ ਲਈ ਕਿਨਾਰੇ \'ਤੇ ਲਿਜਾਓ"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"ਅਣਕੀਤਾ ਕਰੋ"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"ਪਹੁੰਚਯੋਗਤਾ ਬਟਨ ਨੂੰ ਲੁਕਾਇਆ ਗਿਆ"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"ਪਹੁੰਚਯੋਗਤਾ ਬਟਨ ਦਿਖਾਉਣ ਲਈ ਟੈਪ ਕਰੋ"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> ਸ਼ਾਰਟਕੱਟ ਨੂੰ ਹਟਾਇਆ ਗਿਆ"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# ਸ਼ਾਰਟਕੱਟ ਨੂੰ ਹਟਾਇਆ ਗਿਆ}one{# ਸ਼ਾਰਟਕੱਟ ਨੂੰ ਹਟਾਇਆ ਗਿਆ}other{# ਸ਼ਾਰਟਕੱਟਾਂ ਨੂੰ ਹਟਾਇਆ ਗਿਆ}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"ਉੱਪਰ ਵੱਲ ਖੱਬੇ ਲਿਜਾਓ"</string> diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml index c569f62e448d..192614b17e09 100644 --- a/packages/SystemUI/res/values-pl/strings.xml +++ b/packages/SystemUI/res/values-pl/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Nie udało się skonfigurować rozpoznawania twarzy. Przejdź do ustawień, aby spróbować jeszcze raz."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Dotknij czytnika linii papilarnych"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Aby kontynuować, kliknij ikonę odblokowywania"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"Nie rozpoznano twarzy. Użyj odcisku palca."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"Nie rozpoznano twarzy"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Użyj odcisku palca"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"Rozpoznawanie twarzy niedostępne"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth połączony."</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ładowanie • Pełne naładowanie za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Aby uruchomić wspólny samouczek, przeciągnij palcem w lewo"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Otwórz edytor widżetów"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Dostosuj"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Zamknij"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Dodawaj widżety, usuwaj je i zmieniaj ich kolejność w tym obszarze"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Dodaj więcej widżetów"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Przytrzymaj, aby dostosować widżety"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"Usuń"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Dodaj widżet"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Gotowe"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"Włączyć Bluetooth?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"Aby połączyć klawiaturę z tabletem, musisz najpierw włączyć Bluetooth."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Włącz"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Zaawansowane ustawienia powiadomień"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Włączono – na podstawie twarzy"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"Dzięki zaawansowanym ustawieniom możesz określić poziom ważności powiadomień z aplikacji w skali od 0 do 5. \n\n"<b>"Poziom 5"</b>" \n– Pokazuj u góry listy powiadomień \n– Zezwalaj na powiadomienia na pełnym ekranie \n– Zawsze pokazuj podgląd \n\n"<b>"Poziom 4"</b>" \n– Wyłącz powiadomienia na pełnym ekranie \n– Zawsze pokazuj podgląd \n\n"<b>"Poziom 3"</b>" \n– Wyłącz powiadomienia na pełnym ekranie \n– Nigdy nie pokazuj podglądu \n\n"<b>"Poziom 2"</b>" \n– Wyłącz powiadomienia na pełnym ekranie \n– Nigdy nie pokazuj podglądu \n– NIgdy nie powiadamiaj dźwiękiem ani wibracjami \n\n"<b>"Poziom 1"</b>" \n– Wyłącz powiadomienia na pełnym ekranie \n– Nigdy nie pokazuj podglądu \n– NIgdy nie powiadamiaj dźwiękiem ani wibracjami \n– Ukrywaj na ekranie blokady i pasku stanu \n– Pokazuj u dołu listy powiadomień \n\n"<b>"Poziom 0"</b>" \n– Blokuj wszystkie powiadomienia aplikacji"</string> <string name="inline_done_button" msgid="6043094985588909584">"Gotowe"</string> <string name="inline_ok_button" msgid="603075490581280343">"Zastosuj"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Wyłącz powiadomienia"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"Konfiguracja"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"Pamięć wewnętrzna"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"Wskazówki"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"Ułatwienia dostępu"</string> <string name="instant_apps" msgid="8337185853050247304">"Aplikacje błyskawiczne"</string> <string name="instant_apps_title" msgid="8942706782103036910">"Aplikacja <xliff:g id="APP">%1$s</xliff:g> działa"</string> <string name="instant_apps_message" msgid="6112428971833011754">"Aplikacja została otwarta bez zainstalowania."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Kliknij, aby otworzyć ułatwienia dostępu. Dostosuj lub zmień ten przycisk w Ustawieniach.\n\n"<annotation id="link">"Wyświetl ustawienia"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Przesuń przycisk do krawędzi, aby ukryć go tymczasowo"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Cofnij"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"Ukryto przycisk ułatwień dostępu"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Kliknij, aby wyświetlić przycisk ułatwień dostępu"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> – skrót został usunięty"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# skrót został usunięty}few{# skróty zostały usunięte}many{# skrótów zostało usuniętych}other{# skrótu zostało usunięte}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Przenieś w lewy górny róg"</string> diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml index 001872ab6a54..3ca10d36f9be 100644 --- a/packages/SystemUI/res/values-pt-rBR/strings.xml +++ b/packages/SystemUI/res/values-pt-rBR/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Não foi possível configurar o Desbloqueio facial. Acesse as Configurações e tente de novo."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Toque no sensor de impressão digital"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Pressione o ícone de desbloqueio para continuar"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"Rosto não reconhecido. Use a impressão digital."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"Rosto não reconhecido"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Use a impressão digital"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"O Desbloqueio facial não está disponível"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth conectado."</string> @@ -419,8 +417,7 @@ <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Dispensar"</string> <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Adicione, remova e reorganize seus widgets neste espaço"</string> <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Adicione mais widgets"</string> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Mantenha pressionado para personalizar widgets"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"Remover"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Adicionar widget"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Concluído"</string> @@ -607,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"Ativar o Bluetooth?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"Para conectar o teclado ao tablet, é preciso primeiro ativar o Bluetooth."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Ativar"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Controles de ativação/desativação de notificações"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Ativada (reconhecimento facial)"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"Com controles de ativação de notificações, é possível definir o nível de importância de 0 a 5 para as notificações de um app. \n\n"<b>"Nível 5"</b>" \n- Exibir na parte superior da lista de notificações \n- Permitir interrupção em tela cheia \n- Sempre exibir \n\n"<b>"Nível 4"</b>" \n- Impedir interrupções em tela cheia \n- Sempre exibir \n\n"<b>"Nível 3"</b>" \n- Impedir interrupções em tela cheia \n- Nunca exibir \n\n"<b>"Nível 2"</b>" \n- Impedir interrupções em tela cheia \n- Nunca exibir \n- Nunca emitir som ou vibrar \n\n"<b>"Nível 1"</b>" \n- Impedir interrupções em tela cheia \n- Nunca exibir \n- Nunca emitir som ou vibrar \n- Ocultar da tela de bloqueio e barra de status \n- Exibir na parte inferior da lista de notificações \n\n"<b>"Nível 0"</b>" \n- Bloquear todas as notificações do app"</string> <string name="inline_done_button" msgid="6043094985588909584">"Concluído"</string> <string name="inline_ok_button" msgid="603075490581280343">"Aplicar"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Desativar notificações"</string> @@ -842,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"Configurar"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"Armazenamento"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"Dicas"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"Acessibilidade"</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> em execução"</string> <string name="instant_apps_message" msgid="6112428971833011754">"O app é aberto sem precisar ser instalado."</string> @@ -939,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Toque para abrir os recursos de acessibilidade. Personalize ou substitua o botão nas Configurações.\n\n"<annotation id="link">"Ver configurações"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Mova o botão para a borda para ocultá-lo temporariamente"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Desfazer"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"Botão de acessibilidade oculto"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Toque para mostrar o botão de acessibilidade"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Atalho de <xliff:g id="FEATURE_NAME">%s</xliff:g> removido"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# atalho removido}one{# atalho removido}many{# de atalhos removidos}other{# atalhos removidos}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Mover para o canto superior esquerdo"</string> diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml index 44317aefcd1f..1656e279aa57 100644 --- a/packages/SystemUI/res/values-pt-rPT/strings.xml +++ b/packages/SystemUI/res/values-pt-rPT/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Não foi possível configurar o Desbloqueio facial. Aceda às Definições para tentar novamente."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Toque no sensor de impressões digitais."</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Prima o ícone de desbloqueio para continuar"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"Rosto não reconhecido. Use a impressão digital."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"Rosto não reconhecido"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Usar impressão digital"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"Desbloqueio facial indisponível"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth ligado."</string> @@ -419,8 +417,7 @@ <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Ignorar"</string> <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Adicionar, remover e reordenar widgets neste espaço"</string> <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Adicionar mais widgets"</string> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Mantenha premido para personalizar os widgets"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"Remover"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Adicionar widget"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Concluir"</string> @@ -607,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"Ativar o Bluetooth?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"Para ligar o teclado ao tablet, tem de ativar primeiro o Bluetooth."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Ativar"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Controlos de notificações do consumo de energia"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Ativada – Com base no rosto"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"Com os controlos de notificações do consumo de energia, pode definir um nível de importância de 0 a 5 para as notificações de aplicações. \n\n"<b>"Nível 5"</b>" \n- Mostrar no início da lista de notificações \n- Permitir a interrupção do ecrã inteiro \n- Aparecer rapidamente sempre \n\n"<b>"Nível 4"</b>" \n- Impedir a interrupção do ecrã inteiro \n- Aparecer rapidamente sempre\n\n"<b>"Nível 3"</b>" \n- Impedir a interrupção do ecrã inteiro \n- Nunca aparecer rapidamente \n\n"<b>"Nível 2"</b>" \n- Impedir a interrupção do ecrã inteiro \n- Nunca aparecer rapidamente \n- Nunca tocar nem vibrar \n\n"<b>"Nível 1"</b>" \n- Impedir a interrupção do ecrã inteiro \n- Nunca aparecer rapidamente \n- Nunca tocar nem vibrar \n- Ocultar do ecrã de bloqueio e da barra de estado \n- Mostrar no fim da lista de notificações \n\n"<b>"Nível 0"</b>" \n- Bloquear todas as notificações da app"</string> <string name="inline_done_button" msgid="6043094985588909584">"Concluído"</string> <string name="inline_ok_button" msgid="603075490581280343">"Aplicar"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Desativar notificações"</string> @@ -842,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"Configuração"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"Armazenamento"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"Sugestões"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"Acessibilidade"</string> <string name="instant_apps" msgid="8337185853050247304">"Apps instantâneas"</string> <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> em execução"</string> <string name="instant_apps_message" msgid="6112428971833011754">"A app é aberta sem ser instalada."</string> @@ -939,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Toque para abrir funcionalidades de acessibilidade. Personal. ou substitua botão em Defin.\n\n"<annotation id="link">"Ver defin."</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Mova o botão para a extremidade para o ocultar temporariamente"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Anular"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"Botão Acessibilidade oculto"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Toque para mostrar o botão Acessibilidade"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Atalho de <xliff:g id="FEATURE_NAME">%s</xliff:g> removido"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# atalho removido}many{# atalhos removidos}other{# atalhos removidos}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Mover p/ parte sup. esquerda"</string> diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml index 001872ab6a54..3ca10d36f9be 100644 --- a/packages/SystemUI/res/values-pt/strings.xml +++ b/packages/SystemUI/res/values-pt/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Não foi possível configurar o Desbloqueio facial. Acesse as Configurações e tente de novo."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Toque no sensor de impressão digital"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Pressione o ícone de desbloqueio para continuar"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"Rosto não reconhecido. Use a impressão digital."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"Rosto não reconhecido"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Use a impressão digital"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"O Desbloqueio facial não está disponível"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth conectado."</string> @@ -419,8 +417,7 @@ <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Dispensar"</string> <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Adicione, remova e reorganize seus widgets neste espaço"</string> <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Adicione mais widgets"</string> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Mantenha pressionado para personalizar widgets"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"Remover"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Adicionar widget"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Concluído"</string> @@ -607,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"Ativar o Bluetooth?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"Para conectar o teclado ao tablet, é preciso primeiro ativar o Bluetooth."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Ativar"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Controles de ativação/desativação de notificações"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Ativada (reconhecimento facial)"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"Com controles de ativação de notificações, é possível definir o nível de importância de 0 a 5 para as notificações de um app. \n\n"<b>"Nível 5"</b>" \n- Exibir na parte superior da lista de notificações \n- Permitir interrupção em tela cheia \n- Sempre exibir \n\n"<b>"Nível 4"</b>" \n- Impedir interrupções em tela cheia \n- Sempre exibir \n\n"<b>"Nível 3"</b>" \n- Impedir interrupções em tela cheia \n- Nunca exibir \n\n"<b>"Nível 2"</b>" \n- Impedir interrupções em tela cheia \n- Nunca exibir \n- Nunca emitir som ou vibrar \n\n"<b>"Nível 1"</b>" \n- Impedir interrupções em tela cheia \n- Nunca exibir \n- Nunca emitir som ou vibrar \n- Ocultar da tela de bloqueio e barra de status \n- Exibir na parte inferior da lista de notificações \n\n"<b>"Nível 0"</b>" \n- Bloquear todas as notificações do app"</string> <string name="inline_done_button" msgid="6043094985588909584">"Concluído"</string> <string name="inline_ok_button" msgid="603075490581280343">"Aplicar"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Desativar notificações"</string> @@ -842,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"Configurar"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"Armazenamento"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"Dicas"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"Acessibilidade"</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> em execução"</string> <string name="instant_apps_message" msgid="6112428971833011754">"O app é aberto sem precisar ser instalado."</string> @@ -939,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Toque para abrir os recursos de acessibilidade. Personalize ou substitua o botão nas Configurações.\n\n"<annotation id="link">"Ver configurações"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Mova o botão para a borda para ocultá-lo temporariamente"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Desfazer"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"Botão de acessibilidade oculto"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Toque para mostrar o botão de acessibilidade"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Atalho de <xliff:g id="FEATURE_NAME">%s</xliff:g> removido"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# atalho removido}one{# atalho removido}many{# de atalhos removidos}other{# atalhos removidos}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Mover para o canto superior esquerdo"</string> diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml index ab31599d0d4c..fa2aa1a3a207 100644 --- a/packages/SystemUI/res/values-ro/strings.xml +++ b/packages/SystemUI/res/values-ro/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Nu s-a putut configura deblocarea facială. Accesează Setările pentru a încerca din nou."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Atinge senzorul de amprente"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Apasă pe pictograma de deblocare pentru a continua"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"Fața nu a fost recunoscută. Folosește amprenta."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"Față nerecunoscută"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Folosește amprenta"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"Deblocarea facială nu este disponibilă"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Conectat prin Bluetooth."</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Se încarcă • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> până la încărcarea completă"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Glisează spre stânga pentru a începe tutorialul pentru comunitate"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Deschide editorul de widgeturi"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personalizează"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Respinge"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Adaugă, elimină și reordonează widgeturile în acest spațiu"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Adaugă mai multe widgeturi"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Apasă lung pentru a personaliza widgeturi"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"Elimină"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Adaugă un widget"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Gata"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"Activezi Bluetooth?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"Pentru a conecta tastatura la tabletă, mai întâi trebuie să activezi Bluetooth."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Activează"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Comenzi de gestionare a notificărilor"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Activată – În funcție de chip"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"Folosind comenzile de gestionare a notificărilor, poți seta un nivel de importanță de la 0 la 5 pentru notificările unei aplicații. \n\n"<b>"Nivelul 5"</b>" \n– Se afișează la începutul listei de notificări \n– Se permite întreruperea pe ecranul complet \n– Se afișează întotdeauna scurt \n\n"<b>"Nivelul 4"</b>" \n– Se împiedică întreruperea pe ecranul complet \n– Se afișează întotdeauna scurt \n\n"<b>"Nivelul 3"</b>" \n– Se împiedică întreruperea pe ecranul complet \n– Nu se afișează niciodată scurt \n\n"<b>"Nivelul 2"</b>" \n– Se împiedică întreruperea pe ecranul complet \n– Nu se afișează niciodată scurt \n– Nu se emit sunete și nu vibrează niciodată \n\n"<b>"Nivelul 1"</b>" \n– Se împiedică întreruperea pe ecranul complet \n– Nu se afișează niciodată scurt \n– Nu se emit sunete și nu vibrează niciodată \n– Se ascunde în ecranul de blocare și în bara de stare \n– Se afișează la finalul listei de notificări \n\n"<b>"Nivelul 0"</b>" \n– Se blochează toate notificările din aplicație"</string> <string name="inline_done_button" msgid="6043094985588909584">"Gata"</string> <string name="inline_ok_button" msgid="603075490581280343">"Aplică"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Dezactivează notificările"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"Configurarea"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"Stocare"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"Indicii"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"Accesibilitate"</string> <string name="instant_apps" msgid="8337185853050247304">"Aplicații instantanee"</string> <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> rulează"</string> <string name="instant_apps_message" msgid="6112428971833011754">"Aplicația a fost deschisă fără a fi instalată."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Atinge ca să deschizi funcțiile de accesibilitate. Personalizează sau înlocuiește butonul în setări.\n\n"<annotation id="link">"Vezi setările"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Mută butonul spre margine pentru a-l ascunde temporar"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Anulează"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"Butonul de accesibilitate a fost ascuns"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Atinge pentru a afișa butonul de accesibilitate"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Comandă rapidă <xliff:g id="FEATURE_NAME">%s</xliff:g> eliminată"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# comandă rapidă eliminată}few{# comenzi rapide eliminate}other{# de comenzi rapide eliminate}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Mută în stânga sus"</string> diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml index b6ff0dbdc710..7cb509fd76cc 100644 --- a/packages/SystemUI/res/values-ru/strings.xml +++ b/packages/SystemUI/res/values-ru/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Не удалось настроить фейсконтроль. Перейдите в настройки и повторите попытку."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Прикоснитесь к сканеру отпечатков пальцев."</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Нажмите на значок разблокировки."</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"Лицо не распознано. Сканируйте отпечаток пальца."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"Лицо не распознано."</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Используйте отпечаток."</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"Фейсконтроль недоступен"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth-соединение установлено."</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Зарядка • Осталось <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Чтобы ознакомиться с руководством, проведите по экрану влево"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Открыть редактор виджетов"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Настроить"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Закрыть"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Добавление, удаление и упорядочивание виджетов в этом пространстве"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Добавить виджеты"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Нажмите и удерживайте, чтобы настроить виджеты."</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"Удалить"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Добавить виджет"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Готово"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"Подключение по Bluetooth"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"Чтобы подключить клавиатуру к планшету, включите Bluetooth."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Включить"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Расширенное управление уведомлениями"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Включить (на основе распознавания лиц)"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"С помощью этой функции вы можете устанавливать уровень важности уведомлений от 0 до 5 для каждого приложения.\n\n"<b>"Уровень 5"</b>\n"‒ Помещать уведомления в начало списка.\n‒ Показывать полноэкранные уведомления.\n‒ Показывать всплывающие уведомления.\nУровень 4\n"<b></b>\n"‒ Не показывать полноэкранные уведомления.\n‒ Показывать всплывающие уведомления.\nУровень 3\n"<b></b>\n"‒ Не показывать полноэкранные уведомления.\n‒ Не показывать всплывающие уведомления.\nУровень 2\n"<b></b>\n"‒ Не показывать полноэкранные уведомления.\n‒ Не показывать всплывающие уведомления.\n‒ Не использовать звук и вибрацию.\nУровень 1\n"<b></b>\n"‒ Не показывать полноэкранные уведомления.\n‒ Не показывать всплывающие уведомления.\n‒ Не использовать звук и вибрацию.\n‒ Не показывать на экране блокировки и в строке состояния.\n‒ Помещать уведомления в конец списка.\nУровень 0\n"<b></b>\n"‒ Блокировать все уведомления приложения."</string> <string name="inline_done_button" msgid="6043094985588909584">"Готово"</string> <string name="inline_ok_button" msgid="603075490581280343">"Применить"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Выключить уведомления"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"Настройка"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"Хранилище"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"Подсказки"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"Специальные возможности"</string> <string name="instant_apps" msgid="8337185853050247304">"Приложения с мгновенным запуском"</string> <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> уже здесь!"</string> <string name="instant_apps_message" msgid="6112428971833011754">"Приложение готово к работе, установка не требуется."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Нажмите, чтобы открыть спец. возможности. Настройте или замените эту кнопку в настройках.\n\n"<annotation id="link">"Настройки"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Чтобы временно скрыть кнопку, переместите ее к краю экрана"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Отменить"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"Кнопка специальных возможностей скрыта"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Чтобы вернуть ее, нажмите на уведомление."</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g>: сочетание клавиш удалено."</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# сочетание клавиш удалено}one{# сочетание клавиш удалено}few{# сочетания клавиш удалено}many{# сочетаний клавиш удалено}other{# сочетания клавиш удалено}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Перенести в левый верхний угол"</string> diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml index 5c9faab8680e..97d1c3de59e9 100644 --- a/packages/SystemUI/res/values-si/strings.xml +++ b/packages/SystemUI/res/values-si/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"මුහුණෙන් අගුළු හැරීම පිහිටුවිය නොහැකි විය. නැවත උත්සාහ කිරීමට සැකසීම් වෙත යන්න."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"ඇඟිලි සලකුණු සංවේදකය ස්පර්ශ කරන්න"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"ඉදිරියට යාමට අගුළු ඇරීමේ නිරූපකය ඔබන්න"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"මුහුණ හඳුනා නොගැනිණි. ඒ වෙනුවට ඇඟිලි සලකුණ භාවිත කරන්න."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"මුහුණ හඳුනා නොගන්නා ලදි"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"ඒ වෙනුවට ඇඟිලි සලකුණ භාවිත කරන්න"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"මුහුණෙන් අගුළු ඇරීම නැත"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"බ්ලූටූත් සම්බන්ධිතයි."</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • ආරෝපණය වෙමින් • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>කින් සම්පූර්ණ වේ"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"පොදු නිබන්ධනය ආරම්භ කිරීමට වමට ස්වයිප් කරන්න"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"විජට් සංස්කාරකය විවෘත කරන්න"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"අභිරුචිකරණය කරන්න"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"අස් කරන්න"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"මෙම අවකාශය තුළ ඔබේ විජට් එක් කරන්න, ඉවත් කරන්න, සහ නැවත අනුපිළිවෙල කරන්න"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"තවත් විජට් එක් කරන්න"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"විජට් අභිරුචිකරණය කිරීමට දිගු ඔබන්න"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"ඉවත් කරන්න"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"විජට්ටුව එක් කරන්න"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"නිමයි"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"බ්ලූටූත් ක්රියාත්මක කරන්නද?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"ඔබේ යතුරු පුවරුව ඔබේ ටැබ්ලට් පරිගණකයට සම්බන්ධ කිරීමට, ඔබ පළමුව බ්ලූටූත් ක්රියාත්මක කළ යුතුය."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"ක්රියාත්මක කරන්න"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"බල දැනුම්දීම් පාලන"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"ක්රියාත්මකයි - මුහුණ-පදනම්ව"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"බල දැනුම්දීම් පාලන සමගින්, ඔබට යෙදුමක දැනුම්දීම් සඳහා වැදගත්කම 0 සිට 5 දක්වා සැකසිය හැකිය. \n\n"<b>"5 මට්ටම"</b>" \n- දැනුම්දීම් ලැයිස්තුවේ ඉහළින්ම පෙන්වන්න \n- පූර්ණ තිර බාධාවට ඉඩ දෙන්න \n- සැම විට එබී බලන්න \n\n"<b>"4 මට්ටම"</b>" \n- පූර්ණ තිර බාධාව වළක්වන්න \n- සැම විට එබී බලන්න \n\n"<b>"3 මට්ටම"</b>" \n- පූර්ණ තිර බාධාව වළක්වන්න \n- කිසි විටක එබී නොබලන්න \n\n"<b>"2 මට්ටම"</b>" \n- පූර්ණ තිර බාධාව වළක්වන්න \n- කිසි විටක එබී නොබලන්න \n- කිසි විටක හඬ සහ කම්පනය සිදු නොකරන්න \n\n"<b>"1 මට්ටම"</b>" \n- පූර්ණ තිර බාධාව වළක්වන්න \n- කිසි විටක එබී නොබලන්න \n- කිසි විටක හඬ සහ කම්පනය සිදු නොකරන්න \n- අගුලු තිරය සහ තත්ත්ව තීරුව වෙතින් සඟවන්න \n- දැනුම්දීම් ලැයිස්තුවේ පහළින්ම පෙන්වන්න \n\n"<b>"0 මට්ටම"</b>" \n- යෙදුම වෙතින් වන සියලු දැනුම් දීම් සඟවන්න."</string> <string name="inline_done_button" msgid="6043094985588909584">"නිමයි"</string> <string name="inline_ok_button" msgid="603075490581280343">"යොදන්න"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"දැනුම්දීම් අක්රිය කරන්න"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"පිහිටුවීම"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"ගබඩාව"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"ඉඟි"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"ප්රවේශ්යතාව"</string> <string name="instant_apps" msgid="8337185853050247304">"ක්ෂණික යෙදුම්"</string> <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> ධාවනය වෙමින්"</string> <string name="instant_apps_message" msgid="6112428971833011754">"ස්ථාපනය නොකර යෙදුම විවෘත කර ඇත."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"ප්රවේශ්යතා විශේෂාංග විවෘත කිරීමට තට්ටු කරන්න. සැකසීම් තුළ මෙම බොත්තම අභිරුචිකරණය හෝ ප්රතිස්ථාපනය කරන්න.\n\n"<annotation id="link">"සැකසීම් බලන්න"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"එය තාවකාලිකව සැඟවීමට බොත්තම දාරයට ගෙන යන්න"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"අස් කරන්න"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"ප්රවේශ්යතා බොත්තම සඟවා ඇත"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"ප්රවේශ්යතා බොත්තම පෙන්වීමට තට්ටු කරන්න"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> කෙටිමඟ ඉවත් කළා"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# කෙටිමඟක් ඉවත් කළා}one{කෙටිමං #ක් ඉවත් කළා}other{කෙටිමං #ක් ඉවත් කළා}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"ඉහළ වමට ගෙන යන්න"</string> diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml index ae567c7804d9..f1ff09e38cf9 100644 --- a/packages/SystemUI/res/values-sk/strings.xml +++ b/packages/SystemUI/res/values-sk/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Odomknutie tvárou sa nepodarilo nastaviť. Prejdite do Nastavení a skúste to znova."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Dotknite sa senzora odtlačkov prstov"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Pokračujte stlačením ikony odomknutia"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"Tvár nebola rozpoznaná. Použite odtlačok prsta."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"Tvár nebola rozpoznaná"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Používať radšej odtlačok"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"Odomknutie tvárou nie je k dispozícii"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth pripojené."</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Nabíja sa • Do úplného nabitia zostáva <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Potiahnutím doľava spustite komunitný návod"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Otvoriť editor miniaplikácií"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Prispôsobiť"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Zavrieť"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Pridávajte aj odstraňujte miniaplikácie a meňte ich poradie v tomto priestore"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Pridať ďalšie miniaplikácie"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Miniaplikácie prispôsobíte dlhým stlačením"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"Odstrániť"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Pridať miniaplikáciu"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Hotovo"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"Zapnúť Bluetooth?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"Ak chcete klávesnicu pripojiť k tabletu, najprv musíte zapnúť Bluetooth."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Zapnúť"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Ovládacie prvky zobrazovania upozornení"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Zapnuté – podľa tváre"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"Pomocou ovládacích prvkov zobrazovania upozornení môžete nastaviť pre upozornenia aplikácie úroveň dôležitosti od 0 do 5. \n\n"<b>"Úroveň 5"</b>" \n– Zobrazovať v hornej časti zoznamu upozornení. \n– Povoliť prerušenia na celú obrazovku. \n– Vždy zobrazovať čiastočne. \n\n"<b>"Úroveň 4"</b>" \n– Zabrániť prerušeniam na celú obrazovku. \n– Vždy zobrazovať čiastočne. \n\n"<b>"Úroveň 3"</b>" \n– Zabrániť prerušeniam na celú obrazovku. \n– Nikdy nezobrazovať čiastočne. \n\n"<b>"Úroveň 2"</b>" \n– Zabrániť prerušeniam na celú obrazovku. \n– Nikdy nezobrazovať čiastočne. \n– Nikdy nespúšťať zvuk ani vibrácie. \n\n"<b>"Úroveň 1"</b>" \n– Zabrániť prerušeniam na celú obrazovku. \n– Nikdy nezobrazovať čiastočne. \n– Nikdy nespúšťať zvuk ani vibrácie. \n– Skryť na uzamknutej obrazovke a v stavovom riadku. \n– Zobraziť v dolnej časti zoznamu upozornení. \n\n"<b>"Úroveň 0"</b>" \n– Blokovať všetky upozornenia z aplikácie."</string> <string name="inline_done_button" msgid="6043094985588909584">"Hotovo"</string> <string name="inline_ok_button" msgid="603075490581280343">"Použiť"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Vypnúť upozornenia"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"Nastavenie"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"Úložisko"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"Tipy"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"Dostupnosť"</string> <string name="instant_apps" msgid="8337185853050247304">"Okamžité aplikácie"</string> <string name="instant_apps_title" msgid="8942706782103036910">"Aplikácia <xliff:g id="APP">%1$s</xliff:g> je spustená"</string> <string name="instant_apps_message" msgid="6112428971833011754">"Aplikácia bola otvorená bez inštalácie."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Funkcie dostupnosti otvoríte klepnutím. Tlačidlo prispôsobte alebo nahraďte v Nastav.\n\n"<annotation id="link">"Zobraz. nast."</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Ak chcete tlačidlo dočasne skryť, presuňte ho k okraju"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Späť"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"Tlačidlo dostupnosti je skryté"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Klepnutím zobrazíte tlačidlo dostupnosti"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Bola odstránená skratka <xliff:g id="FEATURE_NAME">%s</xliff:g>"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{Bola odstránená # skratka}few{Boli odstránené # skratky}many{# shortcuts removed}other{Bolo odstránených # skratiek}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Presunúť doľava nahor"</string> diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml index c2f26936febc..8a9b6240961f 100644 --- a/packages/SystemUI/res/values-sl/strings.xml +++ b/packages/SystemUI/res/values-sl/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Odklepanja z obrazom ni bilo mogoče nastaviti. Odprite nastavitve in poskusite znova."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Dotaknite se tipala prstnih odtisov"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Za nadaljevanje pritisnite ikono za odklepanje"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"Obraz ni prepoznan. Uporabite prstni odtis."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"Obraz ni prepoznan"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Uporabite prstni odtis."</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"Odklepanje z obrazom ni na voljo."</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Povezava Bluetooth vzpostavljena."</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Polnjenje • Napolnjeno čez <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Povlecite levo, da zaženete vadnico za skupnost"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Odpiranje urejevalnika pripomočkov"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Prilagodi"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Opusti"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Dodajajte, odstranjujte in prerazporejajte pripomočke v tem prostoru"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Dodajte več pripomočkov"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Pridržite za prilagajanje pripomočkov"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"Odstrani"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Dodajanje pripomočka"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Končano"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"Želite vklopiti Bluetooth?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"Če želite povezati tipkovnico in tablični računalnik, vklopite Bluetooth."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Vklop"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Kontrolniki za pomembnost obvestil"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Vklopljeno – na podlagi obraza"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"S kontrolniki za pomebnost obvestila je mogoče za obvestila aplikacije nastaviti stopnjo pomembnosti od 0 do 5. \n\n"<b>"Stopnja 5"</b>" \n– Prikaz na vrhu seznama obvestil \n– Omogočanje prekinitev v celozaslonskem načinu \n– Vedno prikaži hitre predoglede \n\n"<b>"Stopnja 4"</b>" \n– Preprečevanje prekinitev v celozaslonskem načinu \n– Vedno prikaži hitre predoglede \n\n"<b>"Stopnja 3"</b>" \n– Preprečevanje prekinitev v celozaslonskem načinu \n– Nikoli ne prikaži hitrih predogledov \n\n"<b>"Stopnja 2"</b>" \n– Preprečevanje prekinitev v celozaslonskem načinu \n– Nikoli ne prikaži hitrih predogledov \n– Nikoli ne uporabi zvoka in vibriranja \n\n"<b>"Stopnja 1"</b>" \n– Preprečevanje prekinitev v celozaslonskem načinu \n– Nikoli ne prikaži hitrih predogledov \n– Nikoli ne uporabi zvoka in vibriranja \n– Skrivanje na zaklenjenem zaslonu in v vrstici stanja \n– Prikaz na dnu seznama obvestil \n\n"<b>"Stopnja 0"</b>" \n– Blokiranje vseh obvestil aplikacije"</string> <string name="inline_done_button" msgid="6043094985588909584">"Končano"</string> <string name="inline_ok_button" msgid="603075490581280343">"Uporabi"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Izklopi obvestila"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"Nastavitev"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"Shramba"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"Namigi"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"Dostopnost"</string> <string name="instant_apps" msgid="8337185853050247304">"Nenamestljive aplikacije"</string> <string name="instant_apps_title" msgid="8942706782103036910">"Aplikacija <xliff:g id="APP">%1$s</xliff:g> se izvaja"</string> <string name="instant_apps_message" msgid="6112428971833011754">"Aplikacija je odprta brez namestitve."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Dotaknite se za funkcije dostopnosti. Ta gumb lahko prilagodite ali zamenjate v nastavitvah.\n\n"<annotation id="link">"Ogled nastavitev"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Če želite gumb začasno skriti, ga premaknite ob rob."</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Razveljavi"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"Gumb za dostopnost je skrit"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Dotaknite se za prikaz gumba za dostopnost"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Odstranjena bližnjica za fun. <xliff:g id="FEATURE_NAME">%s</xliff:g>"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{Odstranjena # bližnjica}one{Odstranjena # bližnjica}two{Odstranjeni # bližnjici}few{Odstranjene # bližnjice}other{Odstranjenih # bližnjic}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Premakni zgoraj levo"</string> diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml index 4443954fb2d1..de68a51d47c4 100644 --- a/packages/SystemUI/res/values-sq/strings.xml +++ b/packages/SystemUI/res/values-sq/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Shkyçja me fytyrë nuk mund të konfigurohej. Shko te \"Cilësimet\" për të provuar përsëri."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Prek sensorin e gjurmës së gishtit"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Shtyp ikonën e shkyçjes për të vazhduar"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"Fytyra nuk njihet. Përdor më mirë gjurmën e gishtit."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"Fytyra nuk njihet"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Përdor më mirë gjurmën e gishtit"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"\"Shkyçja me fytyrë\" nuk ofrohet"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Pajisja është lidhur me \"bluetooth\"."</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Po karikohet • Plot për <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Rrëshqit shpejt majtas për të filluar udhëzuesin e përbashkët"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Hap modifikuesin e miniaplikacionit"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Personalizo"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Hiq"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Shto, hiq dhe rirendit miniaplikacionet e tua në këtë hapësirë"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Shto miniaplikacione të tjera"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Shtyp gjatë për të personalizuar miniaplikacionet"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"Hiq"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Shto miniaplikacionin"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"U krye"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"Të aktivizohet \"bluetooth-i\"?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"Për të lidhur tastierën me tabletin, në fillim duhet të aktivizosh \"bluetooth-in\"."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Aktivizo"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Kontrollet e njoftimit të energjisë"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Aktiv - Në bazë të fytyrës"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"Me kontrollet e njoftimit të energjisë, mund të caktosh një nivel rëndësie nga 0 në 5 për njoftimet e një aplikacioni. \n\n"<b>"Niveli 5"</b>" \n- Shfaq në krye të listës së njoftimeve \n- Lejo ndërprerjen e ekranit të plotë \n- Gjithmonë shfaq shpejt \n\n"<b>"Niveli 4"</b>" \n- Parandalo ndërprerjen e ekranit të plotë \n- Gijthmonë shfaq shpejt \n\n"<b>"Niveli 3"</b>" \n- Parandalo ndërprerjen e ekranit të plotë \n- Asnjëherë mos shfaq shpejt \n\n"<b>"Niveli 2"</b>" \n- Parandalo ndërprerjen e ekranit të plotë \n- Asnjëherë mos shfaq shpejt \n- Asnjëherë mos lësho tingull dhe dridhje \n\n"<b>"Niveli 1"</b>" \n- Parandalo ndërprerjen e ekranit të plotë \n- Asnjëherë mos shfaq shpejt \n- Asnjëherë mos lësho tingull ose dridhje \n- Fshih nga ekrani i kyçjes dhe shiriti i statusit \n- Shfaq në fund të listës së njoftimeve \n\n"<b>"Niveli 0"</b>" \n- Blloko të gjitha njoftimet nga aplikacioni"</string> <string name="inline_done_button" msgid="6043094985588909584">"U krye"</string> <string name="inline_ok_button" msgid="603075490581280343">"Zbato"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Çaktivizo njoftimet"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"Konfigurimi"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"Hapësira ruajtëse"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"Sugjerimet"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"Qasshmëria"</string> <string name="instant_apps" msgid="8337185853050247304">"Aplikacionet e çastit"</string> <string name="instant_apps_title" msgid="8942706782103036910">"Po ekzekutohet <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="instant_apps_message" msgid="6112428971833011754">"Aplikacioni u hap pa u instaluar."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Trokit dhe hap veçoritë e qasshmërisë. Modifiko ose ndërro butonin te \"Cilësimet\".\n\n"<annotation id="link">"Shih cilësimet"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Zhvendose butonin në skaj për ta fshehur përkohësisht"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Zhbëj"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"Butoni i qasshmërisë u fsheh"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Trokit për të shfaqur butonin e qasshmërisë"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Shkurtorja për \"<xliff:g id="FEATURE_NAME">%s</xliff:g>\" u hoq"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# shkurtore u hoq}other{# shkurtore u hoqën}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Zhvendos lart majtas"</string> diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml index ac1d7bfbf512..28ff0abe3295 100644 --- a/packages/SystemUI/res/values-sr/strings.xml +++ b/packages/SystemUI/res/values-sr/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Подешавање откључавања лицем није успело. Идите у Подешавања да бисте пробали поново."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Додирните сензор за отисак прста"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Притисните икону откључавања за наставак"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"Лице није препознато. Користите отисак прста."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"Лице није препознато"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Користите отисак прста"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"Откључавање лицем није доступно"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth је прикључен."</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Пуни се • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до краја пуњења"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Превуците улево да бисте започели заједнички водич"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Отвори уређивач виџета"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Прилагодите"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Одбаци"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Додајте, уклоните и преуредите виџете у овом простору"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Додајте још виџета"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Дуги притисак за прилагођавање виџета"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"Уклони"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Додај виџет"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Готово"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"Желите ли да укључите Bluetooth?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"Да бисте повезали тастатуру са таблетом, прво морате да укључите Bluetooth."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Укључи"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Напредне контроле за обавештења"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Укључено – на основу лица"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"Помоћу напредних контрола за обавештења можете да подесите ниво важности од 0. до 5. за обавештења апликације. \n\n"<b>"5. ниво"</b>" \n– Приказују се у врху листе обавештења \n- Дозволи прекид режима целог екрана \n– Увек завируј \n\n"<b>"4. ниво"</b>" \n– Спречи прекид режима целог екрана \n– Увек завируј \n\n"<b>"3. ниво"</b>" \n– Спречи прекид режима целог екрана \n– Никада не завируј \n\n"<b>"2. ниво"</b>" \n– Спречи прекид режима целог екрана \n– Никада не завируј \n– Никада не производи звук или вибрацију \n\n"<b>"1. ниво"</b>" \n– Спречи прекид режима целог екрана \n– Никада не завируј \n– Никада не производи звук или вибрацију \n– Сакриј на закључаном екрану и статусној траци \n– Приказују се у дну листе обавештења \n\n"<b>"0. ниво"</b>" \n– Блокирај сва обавештења из апликације"</string> <string name="inline_done_button" msgid="6043094985588909584">"Готово"</string> <string name="inline_ok_button" msgid="603075490581280343">"Примени"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Искључи обавештења"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"Подешавање"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"Меморијски простор"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"Савети"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"Приступачност"</string> <string name="instant_apps" msgid="8337185853050247304">"Инстант апликације"</string> <string name="instant_apps_title" msgid="8942706782103036910">"Апликација <xliff:g id="APP">%1$s</xliff:g> је покренута"</string> <string name="instant_apps_message" msgid="6112428971833011754">"Апликација се отворила без инсталирања."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Додирните за функције приступачности. Прилагодите или замените ово дугме у Подешавањима.\n\n"<annotation id="link">"Подешавања"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Померите дугме до ивице да бисте га привремено сакрили"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Опозови"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"Дугме Приступачност је скривено"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Додирните за приказ дугмета Приступачност"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Пречица функције <xliff:g id="FEATURE_NAME">%s</xliff:g> је уклоњена"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# пречица је уклоњена}one{# пречица је уклоњена}few{# пречице су уклоњене}other{# пречица је уклоњено}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Премести горе лево"</string> diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml index f8dbbc590630..8bc214f33cf1 100644 --- a/packages/SystemUI/res/values-sv/strings.xml +++ b/packages/SystemUI/res/values-sv/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Det gick inte att konfigurera ansiktslåset. Öppna inställningarna och försök igen."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Tryck på fingeravtryckssensorn"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Tryck på ikonen lås upp för att fortsätta"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"Ansiktet känns inte igen. Använd fingeravtryck."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"Ansiktet känns inte igen"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Använd fingeravtryck"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"Ansiktslås är otillgängligt"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth ansluten."</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Laddas • Fulladdat om <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Svep åt vänster för att börja med gruppguiden"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Öppna widgetredigeraren"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Anpassa"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Ignorera"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Lägg till, ta bort och ordna om dina widgetar i det här rummet"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Lägg till fler widgetar"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Tryck länge för att anpassa widgetar"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"Ta bort"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Lägg till widget"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Klar"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"Vill du aktivera Bluetooth?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"Om du vill ansluta tangentbordet till surfplattan måste du först aktivera Bluetooth."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Aktivera"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Prioritetsinställningar för aviseringar"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"På – ansiktsbaserad"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"Med aviseringsinställningarna kan du ange prioritetsnivå från 0 till 5 för aviseringar från en app. \n\n"<b>"Nivå 5"</b>" \n– Visa högst upp i aviseringslistan\n– Tillåt avbrott i helskärmsläge \n– Snabbvisa alltid \n\n"<b>"Nivå 4"</b>" \n– Tillåt inte avbrott i helskärmsläge \n– Snabbvisa alltid \n\n"<b>"Nivå 3"</b>" \n- Tillåt inte avbrott i helskärmsläge \n– Snabbvisa aldrig \n\n"<b>"Nivå 2"</b>" \n– Tillåt inte avbrott i helskärmsläge \n– Snabbvisa aldrig \n– Aldrig med ljud eller vibration \n\n"<b>"Nivå 1"</b>" \n– Tillåt inte avbrott i helskärmsläge \n– Snabbvisa aldrig \n– Aldrig med ljud eller vibration \n– Visa inte på låsskärmen och i statusfältet \n– Visa längst ned i aviseringslistan \n\n"<b>"Nivå 0"</b>" \n– Blockera alla aviseringar från appen"</string> <string name="inline_done_button" msgid="6043094985588909584">"Klart"</string> <string name="inline_ok_button" msgid="603075490581280343">"Tillämpa"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Inaktivera aviseringar"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"Konfigurering"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"Lagring"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"Tips"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"Tillgänglighet"</string> <string name="instant_apps" msgid="8337185853050247304">"Snabbappar"</string> <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> körs"</string> <string name="instant_apps_message" msgid="6112428971833011754">"Appen öppnades utan installation."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Tryck för att öppna tillgänglighetsfunktioner. Anpassa/ersätt knappen i Inställningar.\n\n"<annotation id="link">"Inställningar"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Flytta knappen till kanten för att dölja den tillfälligt"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Ångra"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"Tillgänglighetsknappen är dold"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Tryck för att visa tillgänglighetsknapp"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Genväg till <xliff:g id="FEATURE_NAME">%s</xliff:g> har tagits bort"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# genväg har tagits bort}other{# genvägar har tagits bort}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Flytta högst upp till vänster"</string> diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml index dbc2eea39aad..2aec42e48752 100644 --- a/packages/SystemUI/res/values-sw/strings.xml +++ b/packages/SystemUI/res/values-sw/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Imeshindwa kuweka mipangilio ya kufungua kwa uso. Nenda kwenye Mipangilio ili ujaribu tena."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Gusa kitambua alama ya kidole"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Bonyeza aikoni ya kufungua ili uendelee"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"Uso hautambuliki. Tumia alama ya kidole."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"Uso hautambuliki"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Badala yake, tumia alama ya kidole"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"Kipengele cha Kufungua kwa Uso hakipatikani"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth imeunganishwa."</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Inachaji • Itajaa baada ya <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Telezesha kidole kushoto ili uanze mafunzo ya pamoja"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Fungua kihariri cha wijeti"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Weka mapendeleo"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Funga"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Ongeza, ondoa na upange upya wijeti zako katika nafasi hii"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Weka wijeti zingine"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Bonyeza kwa muda mrefu uweke mapendeleo ya wijeti"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"Ondoa"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Ongeza wijeti"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Nimemaliza"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"Je, ungependa kuwasha Bluetooth?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"Ili uunganishe Kibodi yako kwenye kompyuta yako kibao, lazima kwanza uwashe Bluetooth."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Washa"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Udhibiti wa arifa"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Imewashwa - Inayolenga nyuso"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"Ukiwa na udhibiti wa arifa, unaweza kuweka kiwango cha umuhimu wa arifa za programu kuanzia 0 hadi 5. \n\n"<b>"Kiwango cha 5"</b>" \n- Onyesha katika sehemu ya juu ya orodha ya arifa \n- Ruhusu ukatizaji wa skrini nzima \n- Ruhusu arifa za kuchungulia kila wakati\n\n"<b>"Kiwango cha 4"</b>" \n- Zuia ukatizaji wa skrini nzima\n- Ruhusu arifa za kuchungulia kila wakati \n\n"<b>"Kiwango cha 3"</b>" \n- Zuia ukatizaji wa skrini nzima\n- Usiruhusu kamwe arifa za kuchungulia\n\n"<b>"Kiwango cha 2"</b>" \n- Zuia ukatizaji wa skrini nzima\n- Usiruhusu kamwe arifa za kuchungulia \n- Usiruhusu kamwe sauti au mtetemo \n\n"<b>"Kiwango cha 1"</b>" \n- Zuia ukatizaji wa skrini nzima \n- Usiruhusu kamwe arifa za kuchungulia \n- Usiruhusu kamwe sauti na mtetemo \n- Usionyeshe skrini iliyofungwa na sehemu ya arifa \n- Onyesha katika sehemu ya chini ya orodha ya arifa \n\n"<b>"Kiwango cha 0"</b>" \n- Zuia arifa zote kutoka programu"</string> <string name="inline_done_button" msgid="6043094985588909584">"Nimemaliza"</string> <string name="inline_ok_button" msgid="603075490581280343">"Tumia"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Zima arifa"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"Weka mipangilio"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"Hifadhi"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"Vidokezo"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"Ufikivu"</string> <string name="instant_apps" msgid="8337185853050247304">"Programu Zinazofunguka Papo Hapo"</string> <string name="instant_apps_title" msgid="8942706782103036910">"Programu ya <xliff:g id="APP">%1$s</xliff:g> inatumika"</string> <string name="instant_apps_message" msgid="6112428971833011754">"Programu inafunguka bila kusakinishwa."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Gusa ili ufungue vipengele vya ufikivu. Weka mapendeleo au ubadilishe kitufe katika Mipangilio.\n\n"<annotation id="link">"Angalia mipangilio"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Sogeza kitufe kwenye ukingo ili ukifiche kwa muda"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Tendua"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"Kitufe cha zana za ufikivu kimefichwa"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Gusa ili uone kitufe cha zana za ufikivu"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Njia ya mkato ya <xliff:g id="FEATURE_NAME">%s</xliff:g> imeondolewa"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{Njia # ya mkato imeondolewa}other{Njia # za mkato zimeondolewa}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Sogeza juu kushoto"</string> diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml index d70992e2d09d..53190533ec40 100644 --- a/packages/SystemUI/res/values-ta/strings.xml +++ b/packages/SystemUI/res/values-ta/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"\'முகம் காட்டித் திறத்தல்\' அம்சத்தை அமைக்க முடியவில்லை. அமைப்புகளுக்குச் சென்று மீண்டும் முயலவும்."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"கைரேகை சென்சாரைத் தொடவும்"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"தொடர, அன்லாக் ஐகானை அழுத்துங்கள்"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"முகத்தைக் கண்டறிய முடியவில்லை. கைரேகை பயன்படுத்துக"</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"முகம் கண்டறிய முடியவில்லை"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"கைரேகையை உபயோகிக்கவும்"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"முகம் காட்டித் திறத்தல் அம்சம் கிடைக்கவில்லை"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"புளூடூத் இணைக்கப்பட்டது."</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • சார்ஜாகிறது • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> இல் முழுவதும் சார்ஜாகும்"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"சமூகப் பயிற்சியைத் தொடங்க இடதுபுறம் ஸ்வைப் செய்யுங்கள்"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"விட்ஜெட் எடிட்டரைத் திறக்கும்"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"பிரத்தியேகமாக்குங்கள்"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"மூடுக"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"இந்த இடத்தில் உங்கள் விட்ஜெட்களைச் சேர்க்கலாம், அகற்றலாம், மறுவரிசைப்படுத்தலாம்"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"கூடுதல் விட்ஜெட்களைச் சேருங்கள்"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"விட்ஜெட்களைப் பிரத்தியேகமாக்க நீண்ட நேரம் அழுத்துக"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"அகற்றும்"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"விட்ஜெட்டைச் சேர்"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"முடிந்தது"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"புளூடூத்தை இயக்கவா?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"உங்கள் டேப்லெட்டுடன் கீபோர்டை இணைக்க, முதலில் புளூடூத்தை இயக்க வேண்டும்."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"இயக்கு"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"ஆற்றல்மிக்க அறிவிப்புக் கட்டுப்பாடுகள்"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"ஆன் - முகம் அடிப்படையிலானது"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"ஆற்றல்மிக்க அறிவிப்புக் கட்டுப்பாடுகள் மூலம், ஆப்ஸின் அறிவிப்புகளுக்கு முக்கியத்துவ நிலையை (0-5) அமைக்கலாம். \n\n"<b>"நிலை 5"</b>" \n- அறிவிப்புப் பட்டியலின் மேலே காட்டும் \n- முழுத் திரைக் குறுக்கீட்டை அனுமதிக்கும் \n- எப்போதும் நடப்புத் திரையின் மேல் பகுதியில் அறிவிப்புகளைக் காட்டும் \n\n"<b>"நிலை 4"</b>" \n- முழுத் திரைக் குறுக்கீட்டைத் தடுக்கும் \n- எப்போதும் நடப்புத் திரையின் மேல் பகுதியில் அறிவிப்புகளைக் காட்டும் \n\n"<b>"நிலை 3"</b>" \n- முழுத் திரைக் குறுக்கீட்டைத் தடுக்கும் \n- ஒருபோதும் நடப்புத் திரையின் மேல் பகுதியில் அறிவிப்புகளைக் காட்டாது \n\n"<b>"நிலை 2"</b>" \n- முழுத் திரைக் குறுக்கீட்டைத் தடுக்கும் \n- ஒருபோதும் நடப்புத் திரையின் மேல் பகுதியில் அறிவிப்புகளைக் காட்டாது \n- ஒருபோதும் ஒலி எழுப்பாது, அதிர்வுறாது \n\n"<b>"நிலை 1"</b>" \n- முழுத் திரைக் குறுக்கீட்டைத் தடுக்கும் \n- ஒருபோதும் நடப்புத் திரையின் மேல் பகுதியில் அறிவிப்புகளைக் காட்டாது \n- ஒருபோதும் ஒலி எழுப்பாது அல்லது அதிர்வுறாது \n- லாக் ஸ்கிரீன் மற்றும் நிலைப்பட்டியிலிருந்து மறைக்கும் \n- அறிவிப்புகள் பட்டியலின் கீழே காட்டும் \n\n"<b>"நிலை 0"</b>" \n- ஆப்ஸின் எல்லா அறிவிப்புகளையும் தடுக்கும்"</string> <string name="inline_done_button" msgid="6043094985588909584">"முடிந்தது"</string> <string name="inline_ok_button" msgid="603075490581280343">"பயன்படுத்து"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"அறிவிப்புகளை முடக்கு"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"அமைவு"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"சேமிப்பிடம்"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"குறிப்புகள்"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"அணுகல்தன்மை"</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> இயங்குகிறது"</string> <string name="instant_apps_message" msgid="6112428971833011754">"நிறுவ வேண்டிய தேவையில்லாமல் ஆப்ஸ் திறக்கப்பட்டது."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"அணுகல்தன்மை அம்சத்தை திறக்க தட்டவும். அமைப்பில் பட்டனை பிரத்தியேகமாக்கலாம்/மாற்றலாம்.\n\n"<annotation id="link">"அமைப்பில் காண்க"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"பட்டனைத் தற்காலிகமாக மறைக்க ஓரத்திற்கு நகர்த்தும்"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"செயல்தவிர்"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"அணுகல்தன்மை பட்டன் மறைக்கப்பட்டுள்ளது"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"அணுகல்தன்மை பட்டனைக் காட்ட தட்டவும்"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> ஷார்ட்கட் அகற்றப்பட்டது"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# ஷார்ட்கட் அகற்றப்பட்டது}other{# ஷார்ட்கட்கள் அகற்றப்பட்டன}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"மேலே இடதுபுறத்திற்கு நகர்த்து"</string> diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml index c87762e5e6b2..efb8b982c8ef 100644 --- a/packages/SystemUI/res/values-te/strings.xml +++ b/packages/SystemUI/res/values-te/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"ఫేస్ అన్లాక్ను సెటప్ చేయడం సాధ్యపడలేదు. సెట్టింగ్లకు వెళ్లి, ఆపై మళ్లీ ట్రై చేయండి."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"వేలిముద్ర సెన్సార్ను తాకండి"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"కొనసాగించడానికి అన్లాక్ చిహ్నాన్ని నొక్కండి"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"ముఖం గుర్తించలేదు. బదులుగా వేలిముద్ర ఉపయోగించండి."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"ముఖం గుర్తించబడలేదు"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"బదులుగా వేలిముద్రను ఉపయోగించండి"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"ఫేస్ అన్లాక్ అందుబాటులో లేదు"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"బ్లూటూత్ కనెక్ట్ చేయబడింది."</string> @@ -419,8 +417,7 @@ <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"విస్మరించండి"</string> <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"ఈ స్పేస్లో మీ విడ్జెట్లను జోడించండి, తీసివేయండి, క్రమపద్ధతిలో అమర్చండి"</string> <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"మరిన్ని విడ్జెట్లను జోడించండి"</string> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"విడ్జెట్లను అనుకూలీకరించడానికి, నొక్కి, ఉంచండి"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"తీసివేయండి"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"విడ్జెట్ను జోడించండి"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"పూర్తయింది"</string> @@ -607,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"బ్లూటూత్ ఆన్ చేయాలా?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"మీ కీబోర్డ్ను మీ టాబ్లెట్తో కనెక్ట్ చేయడానికి, మీరు ముందుగా బ్లూటూత్ ఆన్ చేయాలి."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"ఆన్ చేయి"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"పవర్ నోటిఫికేషన్ నియంత్రణలు"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"\'ముఖం ఆధారం\'ను - ఆన్ చేయండి"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"పవర్ నోటిఫికేషన్ కంట్రోల్స్ సాయంతో, మీరు యాప్ నోటిఫికేషన్లకు ప్రాముఖ్యతా స్థాయిని 0 నుండి 5 వరకు సెట్ చేయవచ్చు. \n\n"<b>"స్థాయి 5"</b>" \n- నోటిఫికేషన్ లిస్ట్ పైభాగంలో చూపబడతాయి \n- ఫుల్-స్క్రీన్ అంతరాయం అనుమతించబడుతుంది \n- ఎల్లప్పుడూ క్విక్ వీక్షణ అందించబడుతుంది \n\n"<b>"స్థాయి 4"</b>\n"- ఫుల్-స్క్రీన్ అంతరాయం నిరోధించబడుతుంది \n- ఎల్లప్పుడూ క్విక్ వీక్షణ అందించబడుతుంది \n\n"<b>"స్థాయి 3"</b>" \n- ఫుల్-స్క్రీన్ అంతరాయం నిరోధించబడుతుంది \n- ఎప్పుడూ క్విక్ వీక్షణ అందించబడదు \n\n"<b>"స్థాయి 2"</b>" \n- ఫుల్-స్క్రీన్ అంతరాయం నిరోధించబడుతుంది \n- ఎప్పుడూ క్విక్ వీక్షణ అందించబడదు \n- ఎప్పుడూ శబ్దం మరియు వైబ్రేషన్ చేయవు \n\n"<b>"స్థాయి 1"</b>" \n- ఫుల్-స్క్రీన్ అంతరాయం నిరోధించబడుతుంది \n- ఎప్పుడూ క్విక్ వీక్షణ అందించబడదు \n- ఎప్పుడూ శబ్దం లేదా వైబ్రేట్ చేయవు \n- లాక్ స్క్రీన్, స్టేటస్ బార్ల నుండి దాచబడతాయి \n- నోటిఫికేషన్ లిస్ట్ దిగువ భాగంలో చూపబడతాయి \n\n"<b>"స్థాయి 0"</b>" \n- యాప్ నుండి అన్ని నోటిఫికేషన్లు బ్లాక్ చేయబడతాయి"</string> <string name="inline_done_button" msgid="6043094985588909584">"పూర్తయింది"</string> <string name="inline_ok_button" msgid="603075490581280343">"అప్లయి చేయి"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"నోటిఫికేషన్లను ఆఫ్ చేయి"</string> @@ -842,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"సెటప్ చేయండి"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"స్టోరేజ్"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"సూచనలు"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"యాక్సెసిబిలిటీ"</string> <string name="instant_apps" msgid="8337185853050247304">"ఇన్స్టంట్ యాప్లు"</string> <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> అమలవుతోంది"</string> <string name="instant_apps_message" msgid="6112428971833011754">"ఇన్స్టాల్ చేయకుండా యాప్ తెరవబడింది."</string> @@ -939,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"యాక్సెసిబిలిటీ ఫీచర్లను తెరవడానికి ట్యాప్ చేయండి. సెట్టింగ్లలో ఈ బటన్ను అనుకూలంగా మార్చండి లేదా రీప్లేస్ చేయండి.\n\n"<annotation id="link">"వీక్షణ సెట్టింగ్లు"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"తాత్కాలికంగా దానిని దాచడానికి బటన్ను చివరకు తరలించండి"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"చర్య రద్దు చేయండి"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"యాక్సెసిబిలిటీ బటన్ దాచబడింది"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"యాక్సెసిబిలిటీ బటన్ను చూడటానికి ట్యాప్ చేయండి"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> షార్ట్కట్ తీసివేయబడింది"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# షార్ట్కట్ తీసివేయబడింది}other{# షార్ట్కట్లు తీసివేయబడ్డాయి}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"ఎగువ ఎడమ వైపునకు తరలించు"</string> diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml index ab50427a7f6e..78a45d689b17 100644 --- a/packages/SystemUI/res/values-th/strings.xml +++ b/packages/SystemUI/res/values-th/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"ตั้งค่าการปลดล็อกด้วยใบหน้าไม่ได้ ไปที่การตั้งค่าเพื่อลองอีกครั้ง"</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"แตะเซ็นเซอร์ลายนิ้วมือ"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"กดไอคอนปลดล็อกเพื่อดำเนินการต่อ"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"ไม่รู้จักใบหน้า ใช้ลายนิ้วมือแทน"</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"ไม่รู้จักใบหน้า"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"ใช้ลายนิ้วมือแทน"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"การปลดล็อกด้วยใบหน้าไม่พร้อมใช้งาน"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"เชื่อมต่อบลูทูธแล้ว"</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • กำลังชาร์จ • จะเต็มในอีก <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"ปัดไปทางซ้ายเพื่อเริ่มบทแนะนำส่วนกลาง"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"เปิดเครื่องมือแก้ไขวิดเจ็ต"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"ปรับแต่ง"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"ปิด"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"เพิ่ม นำออก และจัดลำดับวิดเจ็ตในพื้นที่นี้ใหม่"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"เพิ่มวิดเจ็ตอีก"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"กดค้างเพื่อปรับแต่งวิดเจ็ต"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"นำออก"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"เพิ่มวิดเจ็ต"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"เสร็จสิ้น"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"เปิดบลูทูธไหม"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"หากต้องการเชื่อมต่อแป้นพิมพ์กับแท็บเล็ต คุณต้องเปิดบลูทูธก่อน"</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"เปิด"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"ส่วนควบคุมการแจ้งเตือนแบบเปิด/ปิด"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"เปิด - ตามใบหน้า"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"ส่วนควบคุมการแจ้งเตือนแบบเปิด/ปิดช่วยให้คุณตั้งค่าระดับความสำคัญสำหรับการแจ้งเตือนของแอปได้ตั้งแต่ระดับ 0-5 \n\n"<b>"ระดับ 5"</b>" \n- แสดงที่ด้านบนของรายการแจ้งเตือน \n- อนุญาตให้รบกวนแบบเต็มหน้าจอ \n- อนุญาตให้แสดงชั่วครู่ \n\n"<b>"ระดับ 4"</b>" \n- ป้องกันการรบกวนแบบเต็มหน้าจอ \n- แสดงชั่วครู่เสมอ \n\n"<b>"ระดับ 3"</b>" \n- ป้องกันการรบกวนแบบเต็มหน้าจอ \n- ไม่แสดงชั่วครู่เลย \n\n"<b>"ระดับ 2"</b>" \n- ป้องกันการรบกวนแบบเต็มหน้าจอ \n- ไม่แสดงชั่วครู่เลย \n- ไม่ส่งเสียงหรือสั่นเลย \n\n"<b>"ระดับ 1"</b>" \n- ป้องกันการรบกวนแบบเต็มหน้าจอ \n- ไม่แสดงชั่วครู่เลย \n- ไม่ส่งเสียงหรือสั่นเลย \n- ซ่อนจากหน้าจอล็อกและแถบสถานะ \n- แสดงที่ด้านล่างของรายการแจ้งเตือน \n\n"<b>"ระดับ 0"</b>" \n- บล็อกการแจ้งเตือนทั้งหมดจากแอป"</string> <string name="inline_done_button" msgid="6043094985588909584">"เสร็จสิ้น"</string> <string name="inline_ok_button" msgid="603075490581280343">"ใช้"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"ปิดการแจ้งเตือน"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"ตั้งค่า"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"พื้นที่เก็บข้อมูล"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"คำแนะนำ"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"การช่วยเหลือพิเศษ"</string> <string name="instant_apps" msgid="8337185853050247304">"Instant App"</string> <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> ทำงานอยู่"</string> <string name="instant_apps_message" msgid="6112428971833011754">"เปิดแอปได้โดยไม่ต้องติดตั้ง"</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"แตะเพื่อเปิดฟีเจอร์การช่วยเหลือพิเศษ ปรับแต่งหรือแทนที่ปุ่มนี้ในการตั้งค่า\n\n"<annotation id="link">"ดูการตั้งค่า"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"ย้ายปุ่มไปที่ขอบเพื่อซ่อนชั่วคราว"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"เลิกทำ"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"ปุ่มการช่วยเหลือพิเศษซ่อนอยู่"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"แตะเพื่อแสดงปุ่มการช่วยเหลือพิเศษ"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"นำทางลัด <xliff:g id="FEATURE_NAME">%s</xliff:g> ออกแล้ว"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{นำทางลัด # รายการออกแล้ว}other{นำทางลัด # รายการออกแล้ว}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"ย้ายไปด้านซ้ายบน"</string> diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml index dcd687a15499..9ede0c73b587 100644 --- a/packages/SystemUI/res/values-tl/strings.xml +++ b/packages/SystemUI/res/values-tl/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Hindi na-set up ang pag-unlock gamit ang mukha. Pumunta sa Mga Setting para subukan ulit."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Pindutin ang fingerprint sensor"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Pindutin ang icon ng pag-unlock para magpatuloy"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"Hindi nakilala ang mukha. Gumamit ng fingerprint."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"Hindi nakilala ang mukha"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Gumamit ng fingerprint"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"Hindi available ang Pag-unlock Gamit ang Mukha"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Nakakonekta ang Bluetooth."</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Nagcha-charge • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> na lang para mapuno"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Mag-swipe pakaliwa para simulan ang communal na tutorial"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Buksan ang editor ng widget"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"I-customize"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"I-dismiss"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Magdagdag, mag-alis, at baguhin ang ayos ng iyong mga widget sa space na ito"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Magdagdag ng higit pang widget"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Pindutin nang matagal para i-customize ang mga widget"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"Alisin"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Magdagdag ng widget"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Tapos na"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"I-on ang Bluetooth?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"Upang ikonekta ang iyong keyboard sa iyong tablet, kailangan mo munang i-on ang Bluetooth."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"I-on"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Mga kontrol sa notification ng power"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Naka-on - Batay sa mukha"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"Sa pamamagitan ng mga kontrol sa notification ng power, magagawa mong itakda ang antas ng kahalagahan ng mga notification ng isang app mula 0 hanggang 5. \n\n"<b>"Antas 5"</b>" \n- Ipakita sa itaas ng listahan ng notification \n- Payagan ang pag-istorbo kapag full screen \n- Palaging sumilip \n\n"<b>"Antas 4"</b>" \n- Pigilan ang pag-istorbo kapag full screen \n- Palaging sumilip \n\n"<b>"Antas 3"</b>" \n- Pigilan ang pag-istorbo kapag full screen \n- Huwag kailanman sumilip \n\n"<b>"Antas 2"</b>" \n- Pigilan ang pag-istorbo kapag full screen \n- Huwag kailanman sumilip \n- Huwag kailanman tumunog o mag-vibrate \n\n"<b>"Antas 1"</b>" \n- Pigilan ang pag-istorbo kapag full screen \n- Huwag kailanman sumilip \n- Huwag kailanman tumunog o mag-vibrate \n- Itago sa lock screen at status bar \n- Ipakita sa ibaba ng listahan ng notification \n\n"<b>"Antas 0"</b>" \n- I-block ang lahat ng notification mula sa app"</string> <string name="inline_done_button" msgid="6043094985588909584">"Tapos na"</string> <string name="inline_ok_button" msgid="603075490581280343">"Ilapat"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"I-off ang mga notification"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"Setup"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"Storage"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"Mga Hint"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"Accessibility"</string> <string name="instant_apps" msgid="8337185853050247304">"Instant Apps"</string> <string name="instant_apps_title" msgid="8942706782103036910">"Tumatakbo ang <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="instant_apps_message" msgid="6112428971833011754">"Nabuksan ang app nang hindi ini-install."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"I-tap, buksan mga feature ng accessibility. I-customize o palitan button sa Mga Setting.\n\n"<annotation id="link">"Tingnan ang mga setting"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Ilipat ang button sa gilid para pansamantala itong itago"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"I-undo"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"Nakatago ang button ng accessibility"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"I-tap para ipakita ang button ng accessibility"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> shortcut ang naalis"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# shortcut ang naalis}one{# shortcut ang naalis}other{# na shortcut ang naalis}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Ilipat sa kaliwa sa itaas"</string> diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml index f04340433697..ef5d06e52daa 100644 --- a/packages/SystemUI/res/values-tr/strings.xml +++ b/packages/SystemUI/res/values-tr/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Yüz tanıma kilidi kurulamadı. Tekrar denemek için Ayarlar\'a gidin."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Parmak izi sensörüne dokunun"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Devam etmek için kilit açma simgesine basın"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"Yüz tanınmadı. Bunun yerine parmak izi kullanın."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"Yüz tanınmadı"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Bunun yerine parmak izi kullanın"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"Yüz Tanıma Kilidi kullanılamıyor"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth bağlandı."</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Şarj oluyor • Dolmasına <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> kaldı"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Ortak eğitimi başlatmak için sola kaydırın"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Widget düzenleyiciyi açın"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Özelleştir"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Kapat"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Bu alanda widget\'larınızı ekleyin, kaldırın ve yeniden sıralayın"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Daha fazla widget ekle"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Widget\'ları özelleştirmek için uzun basın"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"Kaldır"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Widget ekle"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Bitti"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"Bluetooth açılsın mı?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"Klavyenizi tabletinize bağlamak için önce Bluetooth\'u açmanız gerekir."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Aç"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Güç bildirim kontrolleri"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Açık - Yüze göre"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"Güç bildirim kontrolleriyle, bir uygulamanın bildirimleri için 0 ile 5 arasında bir önem düzeyi ayarlayabilirsiniz. \n\n"<b>"5. Düzey"</b>" \n- Bildirim listesinin en üstünde gösterilsin \n- Tam ekran kesintisine izin verilsin \n- Ekranda her zaman kısaca belirsin \n\n"<b>"4. Düzey"</b>" \n- Tam ekran kesintisi engellensin \n- Ekranda her zaman kısaca belirsin \n\n"<b>"3. Düzey"</b>" \n- Tam ekran kesintisi engellensin \n- Ekranda hiçbir zaman kısaca belirmesin \n\n"<b>"2. Düzey"</b>" \n- Tam ekran kesintisi engellensin \n- Ekranda hiçbir zaman belirmesin \n- Hiçbir zaman ses çıkarmasın ve titreştirmesin \n\n"<b>"1. Düzey"</b>" \n- Tam ekran kesintisi engellensin \n- Ekranda hiçbir zaman kısaca belirmesin \n- Hiçbir zaman ses çıkarmasın veya titreştirmesin \n- Kilit ekranından ve durum çubuğundan gizlensin \n- Bildirim listesinin en altında gösterilsin \n\n"<b>"0. Düzey"</b>" \n- Uygulamadan gelen tüm bildirimler engellensin"</string> <string name="inline_done_button" msgid="6043094985588909584">"Bitti"</string> <string name="inline_ok_button" msgid="603075490581280343">"Uygula"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Bildirimleri kapat"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"Kurulum"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"Depolama alanı"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"İpuçları"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"Erişilebilirlik"</string> <string name="instant_apps" msgid="8337185853050247304">"Hazır Uygulamalar"</string> <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> çalışıyor"</string> <string name="instant_apps_message" msgid="6112428971833011754">"Uygulama yüklenmeden açıldı."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Erişilebilirlik özelliklerini açmak için dokunun. Bu düğmeyi Ayarlar\'dan özelleştirin veya değiştirin.\n\n"<annotation id="link">"Ayarları göster"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Düğmeyi geçici olarak gizlemek için kenara taşıyın"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Geri al"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"Erişilebilirlik düğmesi gizlendi"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Erişilebilirlik düğmesini göstermek için dokunun"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> kısayol kaldırıldı"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# kısayol kaldırıldı}other{# kısayol kaldırıldı}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Sol üste taşı"</string> diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml index fce90e5dc897..700a8a0d08c2 100644 --- a/packages/SystemUI/res/values-uk/strings.xml +++ b/packages/SystemUI/res/values-uk/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Не вдалося налаштувати фейс-контроль. Перейдіть у налаштування, щоб повторити спробу."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Торкніться сканера відбитків пальців"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Щоб продовжити, натисніть значок розблокування"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"Обличчя не розпізнано. Скористайтеся відб. пальця."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"Обличчя не розпізнано"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Скористайтеся відбитком"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"Фейс-контроль недоступний"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth під’єднано."</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Заряджання • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> до повного заряду"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Проведіть пальцем уліво, щоб відкрити спільний навчальний посібник"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Відкрити редактор віджетів"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Налаштувати"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Закрити"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Додати, вилучити чи впорядкувати віджети в цьому просторі"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Додати більше віджетів"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Утримуйте, щоб налаштувати віджети"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"Видалити"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Додати віджет"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Готово"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"Увімкнути Bluetooth?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"Щоб під’єднати клавіатуру до планшета, спершу потрібно ввімкнути Bluetooth."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Увімкнути"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Елементи керування сповіщеннями"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Увімкнути (за обличчям)"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"За допомогою елементів керування сповіщеннями ви можете налаштувати пріоритет сповіщень додатка – від 0 до 5 рівня. \n\n"<b>"Рівень 5"</b>\n"- Показувати сповіщення вгорі списку \n- Виводити на весь екран \n- Завжди показувати короткі сповіщення \n\n"<b>"Рівень 4"</b>\n"- Не виводити на весь екран \n- Завжди показувати короткі сповіщення \n\n"<b>"Рівень 3"</b>\n"- Не виводити на весь екран \n- Не показувати короткі сповіщення \n\n"<b>"Рівень 2"</b>\n"- Не виводити на весь екран \n- Не показувати короткі сповіщення \n- Вимкнути звук і вібросигнал \n\n"<b>"Рівень 1"</b>\n"- Не виводити на весь екран \n- Не показувати короткі сповіщення \n- Вимкнути звук і вібросигнал \n- Не показувати на заблокованому екрані та в рядку стану \n- Показувати сповіщення внизу списку \n\n"<b>"Рівень 0"</b>\n"- Блокувати всі сповіщення з додатка"</string> <string name="inline_done_button" msgid="6043094985588909584">"Готово"</string> <string name="inline_ok_button" msgid="603075490581280343">"Застосувати"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Вимкнути сповіщення"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"Налаштування"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"Пам’ять"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"Поради"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"Доступність"</string> <string name="instant_apps" msgid="8337185853050247304">"Додатки з миттєвим запуском"</string> <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> працює"</string> <string name="instant_apps_message" msgid="6112428971833011754">"Додаток відкрито без встановлення."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Торкніться, щоб відкрити функції доступності. Змінити або замінити цю кнопку можна в Налаштуваннях.\n\n"<annotation id="link">"Налаштування"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Щоб тимчасово сховати кнопку, перемістіть її на край екрана"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Відмінити"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"Кнопку функцій доступності приховано"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Натисніть, щоб відобразити кнопку функцій доступності"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g>: швидкий запуск вилучено"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# ярлик вилучено}one{# ярлик вилучено}few{# ярлики вилучено}many{# ярликів вилучено}other{# ярлика вилучено}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Перемістити ліворуч угору"</string> diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml index 1ae2118d1e4d..a1fab6c54e7b 100644 --- a/packages/SystemUI/res/values-ur/strings.xml +++ b/packages/SystemUI/res/values-ur/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"فیس اَن لاک کو سیٹ اپ نہیں کیا جا سکا۔ دوبارہ کوشش کرنے کیلئے ترتیبات پر جائیں۔"</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"فنگر پرنٹ سینسر پر ٹچ کریں"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"جاری رکھنے کیلئے غیر مقفل کرنے کا آئیکن دبائیں"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"چہرے کی شناخت نہیں ہو سکی۔ اس کے بجائے فنگر پرنٹ استعمال کریں۔"</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"چہرے کی شناخت نہیں ہو سکی"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"اس کے بجائے فنگر پرنٹ استعمال کریں"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"فیس اَنلاک غیر دستیاب ہے"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"بلوٹوتھ مربوط ہے۔"</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • چارج ہو رہا ہے • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> میں مکمل"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"کمیونل ٹیوٹوریل شروع کرنے کے لیے بائیں سوائپ کریں"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"ویجیٹ ایڈیٹر کو کھولیں"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"حسب ضرورت بنائیں"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"برخاست کریں"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"اس اسپیس میں اپنے ویجٹس شامل کریں، ہٹائیں اور دوبارہ ترتیب دیں"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"مزید ویجٹس شامل کریں"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"ویجٹس کو حسب ضرورت بنانے کے لیے لانگ پریس کریں"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"ہٹائیں"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"ویجیٹ شامل کریں"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"ہو گیا"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"بلوٹوتھ آن کریں؟"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"اپنے کی بورڈ کو اپنے ٹیبلٹ کے ساتھ منسلک کرنے کیلئے پہلے آپ کو اپنا بلو ٹوتھ آن کرنا ہو گا۔"</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"آن کریں"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"پاور اطلاع کے کنٹرولز"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"آن - چہرے پر مبنی"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"پاور اطلاع کنٹرولز کے ساتھ آپ کسی ایپ کی اطلاعات کیلئے 0 سے 5 تک اہمیت کی سطح سیٹ کر سکتے ہیں۔ \n\n"<b>"سطح 5"</b>\n"- اطلاعات کی فہرست کے اوپر دکھائیں \n- پوری اسکرین کی مداخلت کی اجازت دیں \n- ہمیشہ جھانکنا\n\n"<b>"سطح 4"</b>\n"- پوری اسکرین کی مداخلت کو روکیں \n- ہمیشہ جھانکنا\n\n"<b>"سطح 3"</b>\n"- پوری اسکرین کی مداخلت کو روکیں \n- کبھی نہ جھانکنا \n\n"<b>"سطح 2"</b>\n"- پوری اسکرین کی مداخلت کو روکیں \n- کبھی نہ جھانکنا \n- کبھی آواز اور ارتعاش پیدا نہ کرنا \n\n"<b>" سطح 1"</b>\n"- پوری اسکرین کی مداخلت کو روکنا \n- کبھی نہ جھانکنا \n- کبھی بھی آواز یا ارتعاش پیدا نہ کرنا\n- مقفل اسکرین اور اسٹیٹس بار سے چھپانا \n - اطلاع کی فہرست کی نیچے دکھانا \n\n"<b>"سطح 0"</b>\n"- ایپ سے تمام اطلاعات مسدود کریں"</string> <string name="inline_done_button" msgid="6043094985588909584">"ہو گیا"</string> <string name="inline_ok_button" msgid="603075490581280343">"لاگو کریں"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"اطلاعات کو آف کریں"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"سیٹ اپ"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"اسٹوریج"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"اشارات"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"ایکسیسبیلٹی"</string> <string name="instant_apps" msgid="8337185853050247304">"فوری ایپس"</string> <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> چل رہی ہے"</string> <string name="instant_apps_message" msgid="6112428971833011754">"انسٹال کیے بغیر کھلنے والی ایپ۔"</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"ایکسیسبیلٹی خصوصیات کھولنے کے لیے تھپتھپائیں۔ ترتیبات میں اس بٹن کو حسب ضرورت بنائیں یا تبدیل کریں۔\n\n"<annotation id="link">"ترتیبات ملاحظہ کریں"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"عارضی طور پر بٹن کو چھپانے کے لئے اسے کنارے پر لے جائیں"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"کالعدم کریں"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"ایکسیسبیلٹی بٹن پوشیدہ ہے"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"ایکسیسبیلٹی بٹن دکھانے کے لیے تھپتھپائیں"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> شارٹ کٹ ہٹا دیا گیا"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# شارٹ کٹ ہٹا دیا گیا}other{# شارٹ کٹس ہٹا دیے گئے}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"اوپر بائیں جانب لے جائیں"</string> diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml index 67d3db87b4f1..6478f52ee1ac 100644 --- a/packages/SystemUI/res/values-uz/strings.xml +++ b/packages/SystemUI/res/values-uz/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Yuz bilan ochish sozlanmadimi. Sozlamalarni ochib, qaytadan urining."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Barmoq izi skaneriga tegining"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Davom etish uchun qulfni ochish belgisini bosing"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"Yuz aniqlanmadi. Barmoq izi orqali urining."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"Yuz aniqlanmadi"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Barmoq izi orqali urining"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"Yuz bilan ochilmaydi."</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth ulandi."</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Quvvat olmoqda • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> qoldi"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Qoʻllanma bilan tanishish uchun chapga suring"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Vidjet muharririni ochish"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Moslash"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Yopish"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Bu xonadagi vidjetlaringizni olib tashlang, tartibini oʻzgartiring va yangisini qoʻshing"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Koʻproq vidjetlar qoʻshish"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Vidjetlarni sozlash uchun bosib turing"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"Olib tashlash"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Vidjet kiritish"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Tayyor"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"Bluetooth yoqilsinmi?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"Klaviaturani planshetingizga ulash uchun Bluetooth xizmatini yoqishingiz kerak."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Yoqish"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Bildirishnomalar uchun kengaytirilgan boshqaruv"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Yoqish - Yuz asosida"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"Bildirishnomalar uchun kengaytirilgan boshqaruv yordamida ilova bildirishnomalarining muhimlik darajasini (0-5) sozlash mumkin. \n\n"<b>"5-daraja"</b>" \n- Bildirishnomani ro‘yxatning boshida ko‘rsatish \n- To‘liq ekranli bildirishnomalarni ko‘rsatish \n- Qalqib chiquvchi bildirishnomalarni ko‘rsatish \n\n"<b>"4-daraja"</b>" \n- To‘liq ekranli bildirishnomalarni ko‘rsatmaslik \n- Qalqib chiquvchi bildirishnomalarni ko‘rsatish \n\n"<b>"3-daraja"</b>" \n- To‘liq ekranli bildirishnomalarni ko‘rsatmaslik \n- Qalqib chiquvchi bildirishnomalarni ko‘rsatmaslik \n\n"<b>"2-daraja"</b>" \n- To‘liq ekranli bildirishnomalarni ko‘rsatmaslik \n- Qalqib chiquvchi bildirishnomalarni ko‘rsatmaslik \n- Ovoz va tebranishdan foydalanmaslik \n\n"<b>"1-daraja"</b>" \n- To‘liq ekranli bildirishnomalarni ko‘rsatmaslik \n- Qalqib chiquvchi bildirishnomalarni ko‘rsatmaslik \n- Ovoz va tebranishdan foydalanmaslik \n- Ekran qulfi va holat qatorida ko‘rsatmaslik \n- Bildirishnomani ro‘yxatning oxirida ko‘rsatish \n\n"<b>"0-daraja"</b>" \n- Ilovadan keladigan barcha bildirishnomalarni bloklash"</string> <string name="inline_done_button" msgid="6043094985588909584">"Tayyor"</string> <string name="inline_ok_button" msgid="603075490581280343">"Tatbiq etish"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Bildirishnoma kelmasin"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"Sozlash"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"Xotira"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"Maslahatlar"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"Qulayliklar"</string> <string name="instant_apps" msgid="8337185853050247304">"Darhol ochiladigan ilovalar"</string> <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> ishlayapti"</string> <string name="instant_apps_message" msgid="6112428971833011754">"Ilova o‘rnatilmasdan ochildi."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Maxsus imkoniyatlarni ochish uchun bosing Sozlamalardan moslay yoki almashtira olasiz.\n\n"<annotation id="link">"Sozlamalar"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Vaqtinchalik berkitish uchun tugmani qirra tomon suring"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Bekor qilish"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"Qulayliklar tugmasi yashirilgan"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Qulayliklar tugmasini koʻrsatish uchun bosing"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"<xliff:g id="FEATURE_NAME">%s</xliff:g> ta yorliq olindi"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{# ta yorliq olindi}other{# ta yorliq olindi}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Yuqori chapga surish"</string> diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml index e4ae7be3b544..e42599290e88 100644 --- a/packages/SystemUI/res/values-vi/strings.xml +++ b/packages/SystemUI/res/values-vi/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Không thiết lập được tính năng Mở khoá bằng khuôn mặt. Hãy chuyển đến phần Cài đặt để thử lại."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Chạm vào cảm biến vân tay"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Nhấn vào biểu tượng mở khoá để tiếp tục"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"Không nhận dạng được khuôn mặt. Hãy dùng vân tay."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"Không thể nhận dạng mặt"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Hãy dùng vân tay"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"Không dùng được tính năng Mở khoá bằng khuôn mặt"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Đã kết nối bluetooth."</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Đang sạc • Sẽ đầy sau <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Vuốt sang trái để bắt đầu xem hướng dẫn chung"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Mở trình chỉnh sửa tiện ích"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Tuỳ chỉnh"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Đóng"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Thêm, xoá và sắp xếp lại các tiện ích trong không gian này."</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Thêm tiện ích khác"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Nhấn và giữ để tuỳ chỉnh tiện ích"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"Xoá"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Thêm tiện ích"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Xong"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"Bật Bluetooth?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"Để kết nối bàn phím với máy tính bảng, trước tiên, bạn phải bật Bluetooth."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Bật"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Điều khiển thông báo nguồn"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Đang bật – Dựa trên khuôn mặt"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"Với các kiểm soát thông báo nguồn, bạn có thể đặt cấp độ quan trọng từ 0 đến 5 cho các thông báo của ứng dụng. \n\n"<b>"Cấp 5"</b>" \n- Hiển thị ở đầu danh sách thông báo \n- Cho phép gián đoạn ở chế độ toàn màn hình \n- Luôn xem nhanh \n\n"<b>"Cấp 4"</b>" \n- Ngăn gián đoạn ở chế độ toàn màn hình \n- Luôn xem nhanh \n\n"<b>"Cấp 3"</b>" \n- Ngăn gián đoạn ở chế độ toàn màn hình \n- Không bao giờ xem nhanh \n\n"<b>"Cấp 2"</b>" \n- Ngăn gián đoạn ở chế độ toàn màn hình \n- Không bao giờ xem nhanh \n- Không bao giờ có âm báo và rung \n\n"<b>"Cấp 1"</b>" \n- Ngăn gián đoạn ở chế độ toàn màn hình \n- Không bao giờ xem nhanh \n- Không bao giờ có âm báo và rung \n- Ẩn khỏi màn hình khóa và thanh trạng thái \n- Hiển thị ở cuối danh sách thông báo \n\n"<b>"Cấp 0"</b>" \n- Chặn tất cả các thông báo từ ứng dụng"</string> <string name="inline_done_button" msgid="6043094985588909584">"Xong"</string> <string name="inline_ok_button" msgid="603075490581280343">"Áp dụng"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Tắt thông báo"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"Thiết lập"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"Bộ nhớ"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"Gợi ý"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"Hỗ trợ tiếp cận"</string> <string name="instant_apps" msgid="8337185853050247304">"Ứng dụng tức thì"</string> <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> đang chạy"</string> <string name="instant_apps_message" msgid="6112428971833011754">"Ứng dụng được mở mà không cần cài đặt."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Nhấn để mở bộ tính năng hỗ trợ tiếp cận. Tuỳ chỉnh/thay thế nút này trong phần Cài đặt.\n\n"<annotation id="link">"Xem chế độ cài đặt"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Di chuyển nút sang cạnh để ẩn nút tạm thời"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Huỷ"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"Đã ẩn nút hỗ trợ tiếp cận"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Nhấn để hiện nút hỗ trợ tiếp cận"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Đã xoá phím tắt dành cho <xliff:g id="FEATURE_NAME">%s</xliff:g>"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{Đã xoá # lối tắt}other{Đã xoá # lối tắt}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Chuyển lên trên cùng bên trái"</string> diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml index 7fd84d918038..1c6fb412356a 100644 --- a/packages/SystemUI/res/values-zh-rCN/strings.xml +++ b/packages/SystemUI/res/values-zh-rCN/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"无法设置“人脸解锁”功能。请前往“设置”重试。"</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"请触摸指纹传感器"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"按下解锁图标即可继续"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"无法识别面孔。请改用指纹。"</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"无法识别面孔"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"改用指纹"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"无法使用人脸解锁功能"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"蓝牙已连接。"</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 正在充电 • 将于 <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>后充满"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"向左滑动即可启动公共教程"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"打开微件编辑器"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"自定义"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"关闭"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"在此空间内添加、移除和重新排列您的微件"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"添加更多微件"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"长按即可自定义微件"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"移除"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"添加微件"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"完成"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"要开启蓝牙吗?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"要将您的键盘连接到平板电脑,您必须先开启蓝牙。"</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"开启"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"高级通知设置"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"已开启 - 基于人脸"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"利用高级通知设置,您可以为应用通知设置从 0 级到 5 级的重要程度等级。\n\n"<b>"5 级"</b>" \n- 在通知列表顶部显示 \n- 允许全屏打扰 \n- 一律短暂显示通知 \n\n"<b>"4 级"</b>" \n- 禁止全屏打扰 \n- 一律短暂显示通知 \n\n"<b>"3 级"</b>" \n- 禁止全屏打扰 \n- 一律不短暂显示通知 \n\n"<b>"2 级"</b>" \n- 禁止全屏打扰 \n- 一律不短暂显示通知 \n- 一律不发出声音或振动 \n\n"<b>"1 级"</b>" \n- 禁止全屏打扰 \n- 一律不短暂显示通知 \n- 一律不发出声音或振动 \n- 不在锁定屏幕和状态栏中显示 \n- 在通知列表底部显示 \n\n"<b>"0 级"</b>" \n- 屏蔽应用的所有通知"</string> <string name="inline_done_button" msgid="6043094985588909584">"完成"</string> <string name="inline_ok_button" msgid="603075490581280343">"应用"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"关闭通知"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"设置"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"存储空间"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"提示"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"无障碍"</string> <string name="instant_apps" msgid="8337185853050247304">"免安装应用"</string> <string name="instant_apps_title" msgid="8942706782103036910">"正在运行<xliff:g id="APP">%1$s</xliff:g>"</string> <string name="instant_apps_message" msgid="6112428971833011754">"已打开免安装应用。"</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"点按即可打开无障碍功能。您可在“设置”中自定义或更换此按钮。\n\n"<annotation id="link">"查看设置"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"将按钮移到边缘,即可暂时将其隐藏"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"撤消"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"“无障碍”按钮已隐藏"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"点按即可显示“无障碍”按钮"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"已移除“<xliff:g id="FEATURE_NAME">%s</xliff:g>”快捷方式"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{已移除 # 个快捷方式}other{已移除 # 个快捷方式}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"移至左上角"</string> diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml index 568f8232f45a..c6a1bd8f27f5 100644 --- a/packages/SystemUI/res/values-zh-rHK/strings.xml +++ b/packages/SystemUI/res/values-zh-rHK/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"無法設定「面孔解鎖」功能,請前往「設定」再試一次。"</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"請輕觸指紋感應器"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"按解鎖圖示即可繼續"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"無法辨識面孔,請改用指紋完成驗證。"</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"無法辨識面孔"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"請改用指紋"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"無法使用面孔解鎖"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"藍牙連線已建立。"</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 充電中 • <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>後充滿電"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"向左滑動即可開始共用教學課程"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"開啟小工具編輯器"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"自訂"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"關閉"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"增、移除小工具,以及調整小工具在此空間中的位置"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"新增更多小工具"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"長按即可自訂小工具"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"移除"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"新增小工具"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"完成"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"要開啟藍牙嗎?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"如要將鍵盤連接至平板電腦,請先開啟藍牙。"</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"開啟"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"通知控制項"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"已開啟 - 根據面孔偵測"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"通知控制項讓你設定應用程式通知的重要性 (0 至 5 級)。\n\n"<b>"第 5 級"</b>" \n- 在通知清單頂部顯示 \n- 允許全螢幕騷擾 \n- 一律顯示通知 \n\n"<b>"第 4 級"</b>" \n- 阻止全螢幕騷擾 \n- 一律顯示通知 \n\n"<b>"第 3 級"</b>" \n- 阻止全螢幕騷擾 \n- 永不顯示通知 \n\n"<b>"第 2 級"</b>" \n- 阻止全螢幕騷擾 \n- 永不顯示通知 \n- 永不發出聲響和震動 \n\n"<b>"第 1 級"</b>" \n- 阻止全螢幕騷擾 \n- 永不顯示通知 \n- 永不發出聲響和震動 \n- 從上鎖畫面和狀態列中隱藏 \n- 在通知清單底部顯示 \n\n"<b>"第 0 級"</b>" \n- 封鎖所有應用程式通知"</string> <string name="inline_done_button" msgid="6043094985588909584">"完成"</string> <string name="inline_ok_button" msgid="603075490581280343">"套用"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"關閉通知"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"設定"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"儲存空間"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"提示"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"無障礙功能"</string> <string name="instant_apps" msgid="8337185853050247304">"免安裝應用程式"</string> <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> 運作中"</string> <string name="instant_apps_message" msgid="6112428971833011754">"已開啟免安裝應用程式。"</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"㩒一下就可以開無障礙功能。喺「設定」度自訂或者取代呢個按鈕。\n\n"<annotation id="link">"查看設定"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"將按鈕移到邊緣即可暫時隱藏"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"復原"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"已隱藏無障礙功能按鈕"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"輕按即可顯示無障礙功能按鈕"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"已移除「<xliff:g id="FEATURE_NAME">%s</xliff:g>」捷徑"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{已移除 # 個捷徑}other{已移除 # 個捷徑}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"移去左上方"</string> diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml index 86e653547d6f..5231a06570d6 100644 --- a/packages/SystemUI/res/values-zh-rTW/strings.xml +++ b/packages/SystemUI/res/values-zh-rTW/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"無法設定人臉解鎖功能,請前往「設定」再試一次。"</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"請輕觸指紋感應器"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"按下「解鎖」圖示即可繼續操作"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"無法辨識臉孔,請改用指紋完成驗證。"</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"無法辨識臉孔"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"請改用指紋"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"無法使用人臉解鎖功能"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"藍牙連線已建立。"</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • 充電中 • 將於 <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>後充飽"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"向左滑動即可啟動通用教學課程"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"開啟小工具編輯器"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"自訂"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"關閉"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"新增、移除小工具,以及調整小工具在這個空間中的位置"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"新增更多小工具"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"長按即可自訂小工具"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"移除"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"新增小工具"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"完成"</string> @@ -579,9 +572,9 @@ <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"有來電和通知時會響鈴 (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string> <string name="system_ui_tuner" msgid="1471348823289954729">"系統使用者介面調整精靈"</string> <string name="status_bar" msgid="4357390266055077437">"狀態列"</string> - <string name="demo_mode" msgid="263484519766901593">"系統 UI 示範模式"</string> - <string name="enable_demo_mode" msgid="3180345364745966431">"啟用示範模式"</string> - <string name="show_demo_mode" msgid="3677956462273059726">"顯示示範模式"</string> + <string name="demo_mode" msgid="263484519766901593">"系統 UI 展示模式"</string> + <string name="enable_demo_mode" msgid="3180345364745966431">"啟用展示模式"</string> + <string name="show_demo_mode" msgid="3677956462273059726">"顯示展示模式"</string> <string name="status_bar_ethernet" msgid="5690979758988647484">"乙太網路"</string> <string name="status_bar_alarm" msgid="87160847643623352">"鬧鐘"</string> <string name="wallet_title" msgid="5369767670735827105">"錢包"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"要開啟藍牙功能嗎?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"如要將鍵盤連線到平板電腦,你必須先開啟藍牙。"</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"開啟"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"電源通知控制項"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"已開啟 - 依臉部方向旋轉"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"只要使用電源通知控制項,你就能為應用程式通知設定從 0 到 5 的重要性等級。\n\n"<b>"等級 5"</b>" \n- 顯示在通知清單頂端 \n- 允許全螢幕通知 \n- 一律允許短暫顯示通知 \n\n"<b>"等級 4"</b>" \n- 禁止全螢幕通知 \n- 一律允許短暫顯示通知 \n\n"<b>"等級 3"</b>" \n- 禁止全螢幕通知 \n- 一律不允許短暫顯示通知 \n\n"<b>"等級 2"</b>" \n- 禁止全螢幕通知 \n- 一律不允許短暫顯示通知 \n- 一律不發出音效或震動 \n\n"<b>"等級 1"</b>" \n- 禁止全螢幕通知 \n- 一律不允許短暫顯示通知 \n- 一律不發出音效或震動 \n- 在鎖定畫面和狀態列中隱藏 \n- 顯示在通知清單底端 \n\n"<b>"等級 0"</b>" \n- 封鎖應用程式的所有通知"</string> <string name="inline_done_button" msgid="6043094985588909584">"完成"</string> <string name="inline_ok_button" msgid="603075490581280343">"套用"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"關閉通知"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"設定"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"儲存空間"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"提示"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"無障礙功能"</string> <string name="instant_apps" msgid="8337185853050247304">"免安裝應用程式"</string> <string name="instant_apps_title" msgid="8942706782103036910">"正在執行「<xliff:g id="APP">%1$s</xliff:g>」"</string> <string name="instant_apps_message" msgid="6112428971833011754">"已開啟免安裝應用程式。"</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"輕觸即可開啟無障礙功能。你可以前往「設定」自訂或更換這個按鈕。\n\n"<annotation id="link">"查看設定"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"將按鈕移到邊緣處即可暫時隱藏"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"復原"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"無障礙工具按鈕已隱藏"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"輕觸即可顯示無障礙工具按鈕"</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"已移除「<xliff:g id="FEATURE_NAME">%s</xliff:g>」捷徑"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{已移除 # 個捷徑}other{已移除 # 個捷徑}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"移到左上方"</string> diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml index 564ba337b1d3..10ee16dfeb28 100644 --- a/packages/SystemUI/res/values-zu/strings.xml +++ b/packages/SystemUI/res/values-zu/strings.xml @@ -188,12 +188,10 @@ <string name="face_reenroll_failure_dialog_content" msgid="7073947334397236935">"Ayikwazanga ukusetha ukuvula ngobuso. Iya Kumasethingi ukuze uzame futhi."</string> <string name="fingerprint_dialog_touch_sensor" msgid="2817887108047658975">"Thinta inzwa yesigxivizo zeminwe"</string> <string name="fingerprint_dialog_authenticated_confirmation" msgid="1603899612957562862">"Cindezela isithonjana sokuvula ukuze uqhubeke"</string> - <!-- no translation found for fingerprint_dialog_use_fingerprint_instead (5542430577183894219) --> - <skip /> + <string name="fingerprint_dialog_use_fingerprint_instead" msgid="5542430577183894219">"Ubuso abaziwa. Sebenzisa izigxivizo zeminwe kunalokho."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (2346762871330729634) --> - <skip /> + <string name="keyguard_face_failed" msgid="2346762871330729634">"Ubuso abaziwa"</string> <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Kunalokho sebenzisa isigxivizo somunwe"</string> <string name="keyguard_face_unlock_unavailable" msgid="1581949044193418736">"Ukuvula ngobuso akutholakali"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth ixhunyiwe"</string> @@ -415,16 +413,11 @@ <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Iyashaja • Izogcwala ngo-<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="communal_tutorial_indicator_text" msgid="4503010353591430123">"Swayiphela kwesokunxele ukuze uqale okokufundisa komphakathi"</string> <string name="button_to_open_widget_editor" msgid="5599945944349057600">"Vula isihleli sewijethi"</string> - <!-- no translation found for cta_tile_button_to_open_widget_editor (3871562362382963878) --> - <skip /> - <!-- no translation found for cta_tile_button_to_dismiss (3377597875997861754) --> - <skip /> - <!-- no translation found for cta_label_to_edit_widget (6496885074209203756) --> - <skip /> - <!-- no translation found for cta_label_to_open_widget_picker (3874946756976360699) --> - <skip /> - <!-- no translation found for popup_on_dismiss_cta_tile_text (8292501780996070019) --> - <skip /> + <string name="cta_tile_button_to_open_widget_editor" msgid="3871562362382963878">"Enza ngendlela oyifisayo"</string> + <string name="cta_tile_button_to_dismiss" msgid="3377597875997861754">"Chitha"</string> + <string name="cta_label_to_edit_widget" msgid="6496885074209203756">"Engeza, susa, futhi uhlele kabusha amawijethi akho kulesi sikhala"</string> + <string name="cta_label_to_open_widget_picker" msgid="3874946756976360699">"Engeza amawijethi engeziwe"</string> + <string name="popup_on_dismiss_cta_tile_text" msgid="8292501780996070019">"Cindezela isikhathi eside ukuze wenze ngokwezifiso amawijethi"</string> <string name="button_to_remove_widget" msgid="3948204829181214098">"Susa"</string> <string name="hub_mode_add_widget_button_text" msgid="4831464661209971729">"Engeza iwijethi"</string> <string name="hub_mode_editing_exit_button_text" msgid="3704686734192264771">"Kwenziwe"</string> @@ -611,9 +604,7 @@ <string name="enable_bluetooth_title" msgid="866883307336662596">"Vula i-Bluetooth?"</string> <string name="enable_bluetooth_message" msgid="6740938333772779717">"Ukuze uxhume ikhibhodi yakho nethebhulethi yakho, kufanele uqale ngokuvula i-Bluetooth."</string> <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"Vula"</string> - <string name="tuner_full_importance_settings" msgid="1388025816553459059">"Izilawuli zesaziso zamandla"</string> <string name="rotation_lock_camera_rotation_on" msgid="789434807790534274">"Vuliwe - Kususelwe kubuso"</string> - <string name="power_notification_controls_description" msgid="1334963837572708952">"Ngezilawuli zesaziso zamandla, ungasetha ileveli ebalulekile kusuka ku-0 kuya ku-5 kusuka kuzaziso zohlelo lokusebenza. \n\n"<b>"Ileveli 5"</b>" \n- Ibonisa phezulu kuhlu lwesaziso \n- Vumela ukuphazamiseka kwesikrini esigcwele \n- Ukuhlola njalo \n\n"<b>"Ileveli 4"</b>" \n- Gwema ukuphazamiseka kwesikrini esigcwele \n- Ukuhlola njalo \n\n"<b>"Ileveli 3"</b>" \n- Gwema ukuphazamiseka kwesikrini esigcwele \n- Ukungahloli \n\n"<b>"Ileveli 2"</b>" \n- Gwema ukuphazamiseka kwesikrini esigcwele \n- Ukungahloli \n- Ungenzi umsindo nokudlidliza \n\n"<b>"Ileveli 1"</b>" \n- Gwema ukuphazamiseka kwesikrini esigcwele \n- Ukungahloli \n- Ungenzi umsindo noma ukudlidliza \n- Fihla kusuka kusikrini sokukhiya nebha yesimo \n- Bonisa phansi kohlu lwesaziso \n\n"<b>"Ileveli 0"</b>" \n- Vimbela zonke izaziso kusuka kuhlelo lokusebenza"</string> <string name="inline_done_button" msgid="6043094985588909584">"Kwenziwe"</string> <string name="inline_ok_button" msgid="603075490581280343">"Faka"</string> <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Vala izaziso"</string> @@ -846,8 +837,7 @@ <string name="notification_channel_setup" msgid="7660580986090760350">"Ukusetha"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"Isitoreji"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"Ukubonisa"</string> - <!-- no translation found for notification_channel_accessibility (8956203986976245820) --> - <skip /> + <string name="notification_channel_accessibility" msgid="8956203986976245820">"Ukufinyeleleka"</string> <string name="instant_apps" msgid="8337185853050247304">"Izinhlelo zokusebenza ezisheshayo"</string> <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> esebenzayo"</string> <string name="instant_apps_message" msgid="6112428971833011754">"Uhlelo lokusebenza luvulwe ngaphndle kokufakwa."</string> @@ -943,10 +933,8 @@ <string name="accessibility_floating_button_migration_tooltip" msgid="5217151214439341902">"Thepha ukuze uvule izakhi zokufinyelela. Enza ngendlela oyifisayo noma shintsha le nkinobho Kumasethingi.\n\n"<annotation id="link">"Buka amasethingi"</annotation></string> <string name="accessibility_floating_button_docking_tooltip" msgid="6814897496767461517">"Hambisa inkinobho onqenqemeni ukuze uyifihle okwesikhashana"</string> <string name="accessibility_floating_button_undo" msgid="511112888715708241">"Hlehlisa"</string> - <!-- no translation found for accessibility_floating_button_hidden_notification_title (4115036997406994799) --> - <skip /> - <!-- no translation found for accessibility_floating_button_hidden_notification_text (1457021647040915658) --> - <skip /> + <string name="accessibility_floating_button_hidden_notification_title" msgid="4115036997406994799">"Inkinobho yokufinyeleleka ifihliwe"</string> + <string name="accessibility_floating_button_hidden_notification_text" msgid="1457021647040915658">"Thepha ukuze ubonise inkinobho yokufinyeleleka."</string> <string name="accessibility_floating_button_undo_message_label_text" msgid="9017658016426242640">"Isinqamuleli se-<xliff:g id="FEATURE_NAME">%s</xliff:g> sisusiwe"</string> <string name="accessibility_floating_button_undo_message_number_text" msgid="4909270290725226075">"{count,plural, =1{Isinqamuleli esingu-# sisusiwe}one{Izinqamuleli ezingu-# zisusiwe}other{Izinqamuleli ezingu-# zisusiwe}}"</string> <string name="accessibility_floating_button_action_move_top_left" msgid="6253520703618545705">"Hamba phezulu kwesokunxele"</string> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index ee2a1ceab2b7..09b02f851c3c 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -151,6 +151,8 @@ <dimen name="status_bar_icon_size_sp">@*android:dimen/status_bar_icon_size_sp</dimen> <!-- Original dp height of notification icons in the status bar --> <dimen name="status_bar_icon_size">@*android:dimen/status_bar_icon_size</dimen> + <dimen name="status_bar_bindable_icon_size">20sp</dimen> + <dimen name="status_bar_bindable_icon_padding">2sp</dimen> <!-- Default horizontal drawable padding for status bar icons. --> <dimen name="status_bar_horizontal_padding">2.5sp</dimen> @@ -1726,6 +1728,12 @@ <dimen name="communal_grid_height">630dp</dimen> <!-- Number of columns for each communal card --> <integer name="communal_grid_columns_per_card">6</integer> + <!-- Width of area on right edge of screen in which swipes will open the communal hub --> + <dimen name="communal_right_edge_swipe_region_width">16dp</dimen> + <!-- Height of area at top of communal hub where swipes should open the notification shade --> + <dimen name="communal_top_edge_swipe_region_height">32dp</dimen> + <!-- Height of area at bottom of communal hub where swipes should open the bouncer --> + <dimen name="communal_bottom_edge_swipe_region_height">32dp</dimen> <dimen name="drag_and_drop_icon_size">70dp</dimen> @@ -1930,5 +1938,9 @@ <dimen name="bouncer_user_switcher_view_mode_view_flipper_bottom_margin">0dp</dimen> <!-- UDFPS view attributes --> - <dimen name="udfps_icon_size">6mm</dimen> + <!-- UDFPS icon size in microns/um --> + <dimen name="udfps_icon_size" format="float">6000</dimen> + <!-- Microns/ums (1000 um = 1mm) per pixel for the given device. If unspecified, UI that + relies on this value will not be sized correctly. --> + <item name="pixel_pitch" format="float" type="dimen">-1</item> </resources> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 7fa35dbb0575..9bc7681665f1 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -3254,7 +3254,7 @@ <string name="install_app">Install app</string> <!-- Instructions informing the user they can swipe up on the lockscreen to dismiss [CHAR LIMIT=48]--> - <string name="dismissible_keyguard_swipe">Swipe to continue</string> + <string name="dismissible_keyguard_swipe">Swipe up to continue</string> <!--- Title of the dialog appearing when an external display is connected, asking whether to start mirroring [CHAR LIMIT=NONE]--> <string name="connected_display_dialog_start_mirroring">Mirror to external display?</string> diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl index 7088829bd2a3..d191a3c3f28b 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl @@ -20,7 +20,6 @@ import android.graphics.Rect; import android.graphics.Region; import android.os.Bundle; import android.view.MotionEvent; -import android.view.SurfaceControl; import com.android.systemui.shared.recents.ISystemUiProxy; // Next ID: 29 @@ -99,11 +98,6 @@ oneway interface IOverviewProxy { void enterStageSplitFromRunningApp(boolean leftOrTop) = 25; /** - * Sent when the surface for navigation bar is created or changed - */ - void onNavigationBarSurface(in SurfaceControl surface) = 26; - - /** * Sent when the task bar stash state is toggled. */ void onTaskbarToggled() = 27; diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java index 033f93b260ab..ad303171d22e 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java @@ -477,9 +477,13 @@ public class KeyguardClockSwitch extends RelativeLayout { public void dump(PrintWriter pw, String[] args) { pw.println("KeyguardClockSwitch:"); pw.println(" mSmallClockFrame = " + mSmallClockFrame); - pw.println(" mSmallClockFrame.alpha = " + mSmallClockFrame.getAlpha()); + if (mSmallClockFrame != null) { + pw.println(" mSmallClockFrame.alpha = " + mSmallClockFrame.getAlpha()); + } pw.println(" mLargeClockFrame = " + mLargeClockFrame); - pw.println(" mLargeClockFrame.alpha = " + mLargeClockFrame.getAlpha()); + if (mLargeClockFrame != null) { + pw.println(" mLargeClockFrame.alpha = " + mLargeClockFrame.getAlpha()); + } pw.println(" mStatusArea = " + mStatusArea); pw.println(" mDisplayedClockSize = " + mDisplayedClockSize); } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java index 8e5d0dac7bef..ecce22315c50 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java @@ -37,6 +37,7 @@ import android.app.ActivityManager; import android.app.admin.DevicePolicyManager; import android.content.Intent; import android.content.res.ColorStateList; +import android.content.res.Configuration; import android.content.res.Resources; import android.hardware.biometrics.BiometricRequestConstants; import android.media.AudioManager; @@ -390,6 +391,11 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard mSecurityViewFlipperController.updateConstraints(useSplitBouncer); } } + + @Override + public void onConfigChanged(Configuration newConfig) { + configureMode(); + } }; private final KeyguardUpdateMonitorCallback mKeyguardUpdateMonitorCallback = new KeyguardUpdateMonitorCallback() { diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index fe96099b0824..3e8c6a76998a 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -1644,11 +1644,11 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab void setAssistantVisible(boolean assistantVisible) { mAssistantVisible = assistantVisible; mLogger.logAssistantVisible(mAssistantVisible); - if (getFaceAuthInteractor() != null) { - getFaceAuthInteractor().onAssistantTriggeredOnLockScreen(); - } updateFingerprintListeningState(BIOMETRIC_ACTION_UPDATE); if (mAssistantVisible) { + if (getFaceAuthInteractor() != null) { + getFaceAuthInteractor().onAssistantTriggeredOnLockScreen(); + } requestActiveUnlock( ActiveUnlockConfig.ActiveUnlockRequestOrigin.ASSISTANT, "assistant", diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayer.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayer.java index 6869bbaedcf3..97999cc19dc8 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayer.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayer.java @@ -240,7 +240,9 @@ class MenuViewLayer extends FrameLayout implements mMenuView.setOnTargetFeaturesChangeListener(newTargetFeatures -> { if (Flags.floatingMenuDragToHide()) { dismissNotification(); - undo(); + if (newTargetFeatures.size() > 0) { + undo(); + } } else { if (newTargetFeatures.size() < 1) { return; diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/UdfpsOverlayInteractor.kt b/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/UdfpsOverlayInteractor.kt index 4fc1b5841047..a77cc1fea6a6 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/UdfpsOverlayInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/UdfpsOverlayInteractor.kt @@ -17,6 +17,7 @@ package com.android.systemui.biometrics.domain.interactor import android.content.Context +import android.util.Log import android.view.MotionEvent import com.android.systemui.biometrics.AuthController import com.android.systemui.biometrics.shared.model.UdfpsOverlayParams @@ -42,12 +43,23 @@ import kotlinx.coroutines.flow.stateIn class UdfpsOverlayInteractor @Inject constructor( - @Application context: Context, + @Application private val context: Context, private val authController: AuthController, private val selectedUserInteractor: SelectedUserInteractor, @Application scope: CoroutineScope ) { - private val iconSize: Int = context.resources.getDimensionPixelSize(R.dimen.udfps_icon_size) + private fun calculateIconSize(): Int { + val pixelPitch = context.resources.getFloat(R.dimen.pixel_pitch) + if (pixelPitch <= 0) { + Log.e( + "UdfpsOverlayInteractor", + "invalid pixelPitch: $pixelPitch. Pixel pitch must be updated per device." + ) + } + return (context.resources.getFloat(R.dimen.udfps_icon_size) / pixelPitch).toInt() + } + + private var iconSize: Int = calculateIconSize() /** Whether a touch is within the under-display fingerprint sensor area */ fun isTouchWithinUdfpsArea(ev: MotionEvent): Boolean { diff --git a/packages/SystemUI/src/com/android/systemui/common/ui/domain/interactor/ConfigurationInteractor.kt b/packages/SystemUI/src/com/android/systemui/common/ui/domain/interactor/ConfigurationInteractor.kt index 13539850a598..5f6ff82c6038 100644 --- a/packages/SystemUI/src/com/android/systemui/common/ui/domain/interactor/ConfigurationInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/common/ui/domain/interactor/ConfigurationInteractor.kt @@ -72,6 +72,9 @@ class ConfigurationInteractor @Inject constructor(private val repository: Config val onAnyConfigurationChange: Flow<Unit> = repository.onAnyConfigurationChange.onStart { emit(Unit) } + /** Emits the new configuration on any configuration change */ + val configurationValues: Flow<Configuration> = repository.configurationValues + /** Emits the current resolution scaling factor */ val scaleForResolution: Flow<Float> = repository.scaleForResolution } diff --git a/packages/SystemUI/src/com/android/systemui/common/ui/view/ViewExt.kt b/packages/SystemUI/src/com/android/systemui/common/ui/view/ViewExt.kt index 8d04e3d338a0..ce798ba3912f 100644 --- a/packages/SystemUI/src/com/android/systemui/common/ui/view/ViewExt.kt +++ b/packages/SystemUI/src/com/android/systemui/common/ui/view/ViewExt.kt @@ -26,3 +26,20 @@ fun View.setImportantForAccessibilityYesNo(value: Boolean) { importantForAccessibility = if (value) View.IMPORTANT_FOR_ACCESSIBILITY_YES else View.IMPORTANT_FOR_ACCESSIBILITY_NO } + +/** + * Can be used to find the nearest parent of a view of a particular type. + * + * Usage: + * ``` + * val textView = view.getNearestParent<TextView>() + * ``` + */ +inline fun <reified T : View> View.getNearestParent(): T? { + var view: Any? = this + while (view is View) { + if (view is T) return view + view = view.parent + } + return null +} diff --git a/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalWidgetRepositoryModule.kt b/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalWidgetRepositoryModule.kt index 52f42c1aba4f..ab0a2d0d232f 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalWidgetRepositoryModule.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalWidgetRepositoryModule.kt @@ -20,8 +20,10 @@ package com.android.systemui.communal.data.repository import android.appwidget.AppWidgetManager import android.content.Context import android.content.res.Resources +import android.os.Looper import com.android.systemui.communal.shared.CommunalWidgetHost import com.android.systemui.communal.widgets.CommunalAppWidgetHost +import com.android.systemui.communal.widgets.WidgetInteractionHandler import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Main @@ -48,8 +50,12 @@ interface CommunalWidgetRepositoryModule { @SysUISingleton @Provides - fun provideCommunalAppWidgetHost(@Application context: Context): CommunalAppWidgetHost { - return CommunalAppWidgetHost(context, APP_WIDGET_HOST_ID) + fun provideCommunalAppWidgetHost( + @Application context: Context, + interactionHandler: WidgetInteractionHandler, + @Main looper: Looper, + ): CommunalAppWidgetHost { + return CommunalAppWidgetHost(context, APP_WIDGET_HOST_ID, interactionHandler, looper) } @SysUISingleton diff --git a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt index b6180cb03416..44b0383e12c6 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt @@ -36,6 +36,7 @@ import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor import com.android.systemui.smartspace.data.repository.SmartspaceRepository +import com.android.systemui.user.data.repository.UserRepository import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -56,12 +57,13 @@ import kotlinx.coroutines.flow.stateIn class CommunalInteractor @Inject constructor( - @Application private val applicationScope: CoroutineScope, + @Application applicationScope: CoroutineScope, private val communalRepository: CommunalRepository, private val widgetRepository: CommunalWidgetRepository, private val communalPrefsRepository: CommunalPrefsRepository, mediaRepository: CommunalMediaRepository, smartspaceRepository: SmartspaceRepository, + userRepository: UserRepository, keyguardInteractor: KeyguardInteractor, private val appWidgetHost: CommunalAppWidgetHost, private val editWidgetsActivityStarter: EditWidgetsActivityStarter @@ -75,7 +77,14 @@ constructor( val isCommunalAvailable: StateFlow<Boolean> = flowOf(isCommunalEnabled) .flatMapLatest { enabled -> - if (enabled) keyguardInteractor.isEncryptedOrLockdown.map { !it } else flowOf(false) + if (enabled) + combine( + keyguardInteractor.isEncryptedOrLockdown, + userRepository.selectedUserInfo, + ) { isEncryptedOrLockdown, selectedUserInfo -> + !isEncryptedOrLockdown && selectedUserInfo.isMain + } + else flowOf(false) } .distinctUntilChanged() .onEach { available -> widgetRepository.updateAppWidgetHostActive(available) } @@ -134,6 +143,17 @@ constructor( val isCommunalShowing: Flow<Boolean> = communalRepository.desiredScene.map { it == CommunalSceneKey.Communal } + /** + * Flow that emits a boolean if the communal UI is fully visible and not in transition. + * + * This will not be true while transitioning to the hub and will turn false immediately when a + * swipe to exit the hub starts. + */ + val isIdleOnCommunal: Flow<Boolean> = + communalRepository.transitionState.map { + it is ObservableCommunalTransitionState.Idle && it.scene == CommunalSceneKey.Communal + } + val isKeyguardVisible: Flow<Boolean> = keyguardInteractor.isKeyguardVisible /** Callback received whenever the [SceneTransitionLayout] finishes a scene transition. */ @@ -252,6 +272,12 @@ constructor( companion object { /** + * The user activity timeout which should be used when the communal hub is opened. A value + * of -1 means that the user's chosen screen timeout will be used instead. + */ + const val AWAKE_INTERVAL_MS = -1 + + /** * Calculates the content size dynamically based on the total number of contents of that * type. * diff --git a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalTutorialInteractor.kt b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalTutorialInteractor.kt index 5ca89f28f1fc..4e5be9b8aa5e 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalTutorialInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalTutorialInteractor.kt @@ -45,14 +45,17 @@ constructor( private val communalTutorialRepository: CommunalTutorialRepository, keyguardInteractor: KeyguardInteractor, private val communalRepository: CommunalRepository, + communalInteractor: CommunalInteractor, ) { /** An observable for whether the tutorial is available. */ val isTutorialAvailable: Flow<Boolean> = combine( + communalInteractor.isCommunalAvailable, keyguardInteractor.isKeyguardVisible, communalTutorialRepository.tutorialSettingState, - ) { isKeyguardVisible, tutorialSettingState -> - isKeyguardVisible && + ) { isCommunalAvailable, isKeyguardVisible, tutorialSettingState -> + isCommunalAvailable && + isKeyguardVisible && tutorialSettingState != Settings.Secure.HUB_MODE_TUTORIAL_COMPLETED } .distinctUntilChanged() diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/BaseCommunalViewModel.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/BaseCommunalViewModel.kt index f1b16c555a6b..acc7981dd460 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/BaseCommunalViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/BaseCommunalViewModel.kt @@ -17,7 +17,6 @@ package com.android.systemui.communal.ui.viewmodel import android.content.ComponentName -import android.widget.RemoteViews import com.android.systemui.communal.domain.interactor.CommunalInteractor import com.android.systemui.communal.domain.model.CommunalContentModel import com.android.systemui.communal.shared.model.CommunalSceneKey @@ -103,9 +102,6 @@ abstract class BaseCommunalViewModel( /** Called as the UI requests to dismiss the CTA tile. */ open fun onDismissCtaTile() {} - /** Gets the interaction handler used to handle taps on a remote view */ - abstract fun getInteractionHandler(): RemoteViews.InteractionHandler - /** Called as the user starts dragging a widget to reorder. */ open fun onReorderWidgetStart() {} diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalEditModeViewModel.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalEditModeViewModel.kt index c69fa6f74c94..237a0c005af5 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalEditModeViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalEditModeViewModel.kt @@ -16,7 +16,6 @@ package com.android.systemui.communal.ui.viewmodel -import android.widget.RemoteViews import com.android.internal.logging.UiEventLogger import com.android.systemui.communal.domain.interactor.CommunalInteractor import com.android.systemui.communal.domain.model.CommunalContentModel @@ -60,11 +59,6 @@ constructor( override fun onReorderWidgets(widgetIdToPriorityMap: Map<Int, Int>) = communalInteractor.updateWidgetOrder(widgetIdToPriorityMap) - override fun getInteractionHandler(): RemoteViews.InteractionHandler { - // Ignore all interactions in edit mode. - return RemoteViews.InteractionHandler { _, _, _ -> false } - } - override fun onReorderWidgetStart() { // Clear selection status setSelectedIndex(null) diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt index d619362b0311..a909383f4a2c 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt @@ -16,11 +16,9 @@ package com.android.systemui.communal.ui.viewmodel -import android.widget.RemoteViews import com.android.systemui.communal.domain.interactor.CommunalInteractor import com.android.systemui.communal.domain.interactor.CommunalTutorialInteractor import com.android.systemui.communal.domain.model.CommunalContentModel -import com.android.systemui.communal.widgets.WidgetInteractionHandler import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.media.controls.ui.MediaHierarchyManager @@ -48,7 +46,6 @@ class CommunalViewModel constructor( @Application private val scope: CoroutineScope, private val communalInteractor: CommunalInteractor, - private val interactionHandler: WidgetInteractionHandler, tutorialInteractor: CommunalTutorialInteractor, @Named(MediaModule.COMMUNAL_HUB) mediaHost: MediaHost, ) : BaseCommunalViewModel(communalInteractor, mediaHost) { @@ -77,6 +74,7 @@ constructor( // before the MediaHierarchyManager attempts to move the UMO to the hub. with(mediaHost) { expansion = MediaHostState.EXPANDED + expandedMatchesParentHeight = true showsOnlyActiveMedia = false falsingProtectionNeeded = false init(MediaHierarchyManager.LOCATION_COMMUNAL_HUB) @@ -93,8 +91,6 @@ constructor( } } - override fun getInteractionHandler(): RemoteViews.InteractionHandler = interactionHandler - override fun onHidePopupAfterDismissCta() { cancelDelayedPopupHiding() setPopupOnDismissCtaVisibility(false) diff --git a/packages/SystemUI/src/com/android/systemui/communal/widgets/CommunalAppWidgetHost.kt b/packages/SystemUI/src/com/android/systemui/communal/widgets/CommunalAppWidgetHost.kt index 003c9d50e789..61db02639788 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/widgets/CommunalAppWidgetHost.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/widgets/CommunalAppWidgetHost.kt @@ -20,9 +20,16 @@ import android.appwidget.AppWidgetHost import android.appwidget.AppWidgetHostView import android.appwidget.AppWidgetProviderInfo import android.content.Context +import android.os.Looper +import android.widget.RemoteViews /** Communal app widget host that creates a [CommunalAppWidgetHostView]. */ -class CommunalAppWidgetHost(context: Context, hostId: Int) : AppWidgetHost(context, hostId) { +class CommunalAppWidgetHost( + context: Context, + hostId: Int, + interactionHandler: RemoteViews.InteractionHandler, + looper: Looper +) : AppWidgetHost(context, hostId, interactionHandler, looper) { override fun onCreateView( context: Context, appWidgetId: Int, diff --git a/packages/SystemUI/src/com/android/systemui/communal/widgets/CommunalAppWidgetHostView.kt b/packages/SystemUI/src/com/android/systemui/communal/widgets/CommunalAppWidgetHostView.kt index 2b7d82395b89..840c3a83b758 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/widgets/CommunalAppWidgetHostView.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/widgets/CommunalAppWidgetHostView.kt @@ -22,9 +22,17 @@ import android.graphics.Outline import android.graphics.Rect import android.view.View import android.view.ViewOutlineProvider +import com.android.systemui.animation.LaunchableView +import com.android.systemui.animation.LaunchableViewDelegate /** AppWidgetHostView that displays in communal hub with support for rounded corners. */ -class CommunalAppWidgetHostView(context: Context) : AppWidgetHostView(context) { +class CommunalAppWidgetHostView(context: Context) : AppWidgetHostView(context), LaunchableView { + private val launchableViewDelegate = + LaunchableViewDelegate( + this, + superSetVisibility = { super.setVisibility(it) }, + ) + // Mutable corner radius. var enforcedCornerRadius: Float @@ -73,4 +81,9 @@ class CommunalAppWidgetHostView(context: Context) : AppWidgetHostView(context) { outlineProvider = ViewOutlineProvider.BACKGROUND clipToOutline = false } + + override fun setShouldBlockVisibilityChanges(block: Boolean) = + launchableViewDelegate.setShouldBlockVisibilityChanges(block) + + override fun setVisibility(visibility: Int) = launchableViewDelegate.setVisibility(visibility) } diff --git a/packages/SystemUI/src/com/android/systemui/communal/widgets/WidgetInteractionHandler.kt b/packages/SystemUI/src/com/android/systemui/communal/widgets/WidgetInteractionHandler.kt index c8db70bbc313..afa7fa9e8f77 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/widgets/WidgetInteractionHandler.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/widgets/WidgetInteractionHandler.kt @@ -19,6 +19,8 @@ package com.android.systemui.communal.widgets import android.app.PendingIntent import android.view.View import android.widget.RemoteViews +import com.android.systemui.animation.ActivityLaunchAnimator +import com.android.systemui.common.ui.view.getNearestParent import com.android.systemui.plugins.ActivityStarter import javax.inject.Inject @@ -33,17 +35,19 @@ constructor( response: RemoteViews.RemoteResponse ): Boolean = when { - pendingIntent.isActivity -> startActivity(pendingIntent) + pendingIntent.isActivity -> startActivity(view, pendingIntent) else -> RemoteViews.startPendingIntent(view, pendingIntent, response.getLaunchOptions(view)) } - private fun startActivity(pendingIntent: PendingIntent): Boolean { + private fun startActivity(view: View, pendingIntent: PendingIntent): Boolean { + val hostView = view.getNearestParent<CommunalAppWidgetHostView>() + val animationController = hostView?.let(ActivityLaunchAnimator.Controller::fromView) + activityStarter.startPendingIntentMaybeDismissingKeyguard( - /* intent = */ pendingIntent, + pendingIntent, /* intentSentUiThreadCallback = */ null, - // TODO(b/318758390): Properly animate activities started from widgets. - /* animationController = */ null + animationController ) return true } diff --git a/packages/SystemUI/src/com/android/systemui/compose/BaseComposeFacade.kt b/packages/SystemUI/src/com/android/systemui/compose/BaseComposeFacade.kt index 641064becf24..2f9fd2e99619 100644 --- a/packages/SystemUI/src/com/android/systemui/compose/BaseComposeFacade.kt +++ b/packages/SystemUI/src/com/android/systemui/compose/BaseComposeFacade.kt @@ -17,6 +17,7 @@ package com.android.systemui.compose +import android.app.Dialog import android.content.Context import android.view.View import android.view.WindowInsets @@ -26,11 +27,13 @@ import com.android.systemui.bouncer.ui.BouncerDialogFactory import com.android.systemui.bouncer.ui.viewmodel.BouncerViewModel import com.android.systemui.communal.ui.viewmodel.BaseCommunalViewModel import com.android.systemui.communal.widgets.WidgetConfigurator +import com.android.systemui.keyboard.stickykeys.ui.viewmodel.StickyKeysIndicatorViewModel import com.android.systemui.people.ui.viewmodel.PeopleViewModel import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel import com.android.systemui.scene.shared.model.Scene import com.android.systemui.scene.shared.model.SceneKey import com.android.systemui.scene.ui.viewmodel.SceneContainerViewModel +import com.android.systemui.statusbar.phone.SystemUIDialogFactory import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.StateFlow @@ -86,6 +89,12 @@ interface BaseComposeFacade { sceneByKey: Map<SceneKey, Scene>, ): View + /** Creates sticky key dialog presenting provided [viewModel] **/ + fun createStickyKeysDialog( + dialogFactory: SystemUIDialogFactory, + viewModel: StickyKeysIndicatorViewModel + ): Dialog + /** Create a [View] to represent [viewModel] on screen. */ fun createCommunalView( context: Context, diff --git a/packages/SystemUI/src/com/android/systemui/doze/dagger/DozeModule.java b/packages/SystemUI/src/com/android/systemui/doze/dagger/DozeModule.java index db0c3c68107a..0fd688760a32 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/dagger/DozeModule.java +++ b/packages/SystemUI/src/com/android/systemui/doze/dagger/DozeModule.java @@ -18,10 +18,7 @@ package com.android.systemui.doze.dagger; import android.content.Context; import android.hardware.Sensor; -import android.os.Handler; -import com.android.systemui.res.R; -import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dagger.qualifiers.UiBackground; import com.android.systemui.doze.DozeAuthRemover; import com.android.systemui.doze.DozeBrightnessHostForwarder; @@ -40,6 +37,7 @@ import com.android.systemui.doze.DozeTransitionListener; import com.android.systemui.doze.DozeTriggers; import com.android.systemui.doze.DozeUi; import com.android.systemui.doze.DozeWallpaperState; +import com.android.systemui.res.R; import com.android.systemui.statusbar.phone.DozeParameters; import com.android.systemui.statusbar.policy.DevicePostureController; import com.android.systemui.util.sensors.AsyncSensorManager; @@ -75,9 +73,8 @@ public abstract class DozeModule { @Provides @DozeScope - static WakeLock providesDozeWakeLock(DelayedWakeLock.Builder delayedWakeLockBuilder, - @Main Handler handler) { - return delayedWakeLockBuilder.setHandler(handler).setTag("Doze").build(); + static WakeLock providesDozeWakeLock(DelayedWakeLock.Factory delayedWakeLockFactory) { + return delayedWakeLockFactory.create("Doze"); } @Provides diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt index 846736c04d98..3f7c152f47d8 100644 --- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt +++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt @@ -574,9 +574,6 @@ object Flags { @JvmField val ENABLE_NEW_PRIVACY_DIALOG = releasedFlag("enable_new_privacy_dialog") - // TODO(b/289573946): Tracking Bug - @JvmField val PRECOMPUTED_TEXT = releasedFlag("precomputed_text") - // TODO(b/302087895): Tracking Bug @JvmField val CALL_LAYOUT_ASYNC_SET_DATA = unreleasedFlag("call_layout_async_set_data", teamfood = true) diff --git a/packages/SystemUI/src/com/android/systemui/haptics/slider/SeekableSliderHapticPlugin.kt b/packages/SystemUI/src/com/android/systemui/haptics/slider/SeekableSliderHapticPlugin.kt new file mode 100644 index 000000000000..58fb6a95b872 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/haptics/slider/SeekableSliderHapticPlugin.kt @@ -0,0 +1,171 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.haptics.slider + +import android.view.MotionEvent +import android.view.VelocityTracker +import android.widget.SeekBar +import androidx.annotation.VisibleForTesting +import com.android.systemui.dagger.qualifiers.Application +import com.android.systemui.dagger.qualifiers.Main +import com.android.systemui.statusbar.VibratorHelper +import com.android.systemui.util.time.SystemClock +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Job +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch + +/** + * A plugin added to a manager of a [android.widget.SeekBar] that adds dynamic haptic feedback. + * + * A [SeekableSliderEventProducer] is used as the producer of slider events, a + * [SliderHapticFeedbackProvider] is used as the listener of slider states to play haptic feedback + * depending on the state, and a [SeekableSliderTracker] is used as the state machine handler that + * tracks and manipulates the slider state. + */ +class SeekableSliderHapticPlugin +@JvmOverloads +constructor( + vibratorHelper: VibratorHelper, + systemClock: SystemClock, + @Main private val mainDispatcher: CoroutineDispatcher, + @Application private val applicationScope: CoroutineScope, + sliderHapticFeedbackConfig: SliderHapticFeedbackConfig = SliderHapticFeedbackConfig(), + sliderTrackerConfig: SeekableSliderTrackerConfig = SeekableSliderTrackerConfig(), +) { + + private val velocityTracker = VelocityTracker.obtain() + + private val sliderEventProducer = SeekableSliderEventProducer() + + private val sliderHapticFeedbackProvider = + SliderHapticFeedbackProvider( + vibratorHelper, + velocityTracker, + sliderHapticFeedbackConfig, + systemClock, + ) + + private val sliderTracker = + SeekableSliderTracker( + sliderHapticFeedbackProvider, + sliderEventProducer, + mainDispatcher, + sliderTrackerConfig, + ) + + val isTracking: Boolean + get() = sliderTracker.isTracking + + val trackerState: SliderState + get() = sliderTracker.currentState + + /** + * A waiting [Job] for a timer that estimates the key-up event when a key-down event is + * received. + * + * This is useful for the cases where the slider is being operated by an external key, but the + * release of the key is not easily accessible (e.g., the volume keys) + */ + private var keyUpJob: Job? = null + + @VisibleForTesting + val isKeyUpTimerWaiting: Boolean + get() = keyUpJob != null && keyUpJob?.isActive == true + + /** + * Start the plugin. + * + * This starts the tracking of slider states, events and triggering of haptic feedback. + */ + fun start() { + if (!isTracking) { + sliderTracker.startTracking() + } + } + + /** + * Stop the plugin + * + * This stops the tracking of slider states, events and triggers of haptic feedback. + */ + fun stop() = sliderTracker.stopTracking() + + /** React to a touch event */ + fun onTouchEvent(event: MotionEvent?) { + when (event?.actionMasked) { + MotionEvent.ACTION_UP, + MotionEvent.ACTION_CANCEL -> velocityTracker.clear() + MotionEvent.ACTION_DOWN, + MotionEvent.ACTION_MOVE -> velocityTracker.addMovement(event) + } + } + + /** onStartTrackingTouch event from the slider's [android.widget.SeekBar] */ + fun onStartTrackingTouch(seekBar: SeekBar) { + if (isTracking) { + sliderEventProducer.onStartTrackingTouch(seekBar) + } + } + + /** onProgressChanged event from the slider's [android.widget.SeekBar] */ + fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) { + if (isTracking) { + sliderEventProducer.onProgressChanged(seekBar, progress, fromUser) + } + } + + /** onStopTrackingTouch event from the slider's [android.widget.SeekBar] */ + fun onStopTrackingTouch(seekBar: SeekBar) { + if (isTracking) { + sliderEventProducer.onStopTrackingTouch(seekBar) + } + } + + /** onArrowUp event recorded */ + fun onArrowUp() { + if (isTracking) { + sliderEventProducer.onArrowUp() + } + } + + /** + * An external key was pressed (e.g., a volume key). + * + * This event is used to estimate the key-up event based on by running a timer as a waiting + * coroutine in the [keyUpTimerScope]. A key-up event in a slider corresponds to an onArrowUp + * event. Therefore, [onArrowUp] must be called after the timeout. + */ + fun onKeyDown() { + if (!isTracking) return + + if (isKeyUpTimerWaiting) { + // Cancel the ongoing wait + keyUpJob?.cancel() + } + keyUpJob = + applicationScope.launch { + delay(KEY_UP_TIMEOUT) + onArrowUp() + } + } + + companion object { + const val KEY_UP_TIMEOUT = 100L + } +} diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/PhysicalKeyboardCoreStartable.kt b/packages/SystemUI/src/com/android/systemui/keyboard/PhysicalKeyboardCoreStartable.kt index d078688e5944..26e83a3f2179 100644 --- a/packages/SystemUI/src/com/android/systemui/keyboard/PhysicalKeyboardCoreStartable.kt +++ b/packages/SystemUI/src/com/android/systemui/keyboard/PhysicalKeyboardCoreStartable.kt @@ -17,11 +17,14 @@ package com.android.systemui.keyboard +import com.android.hardware.input.Flags.keyboardA11yStickyKeysFlag import com.android.systemui.CoreStartable import com.android.systemui.dagger.SysUISingleton import com.android.systemui.flags.FeatureFlags import com.android.systemui.flags.Flags import com.android.systemui.keyboard.backlight.ui.KeyboardBacklightDialogCoordinator +import com.android.systemui.keyboard.stickykeys.ui.StickyKeysIndicatorCoordinator +import dagger.Lazy import javax.inject.Inject /** A [CoreStartable] that launches components interested in physical keyboard interaction. */ @@ -29,12 +32,16 @@ import javax.inject.Inject class PhysicalKeyboardCoreStartable @Inject constructor( - private val keyboardBacklightDialogCoordinator: KeyboardBacklightDialogCoordinator, + private val keyboardBacklightDialogCoordinator: Lazy<KeyboardBacklightDialogCoordinator>, + private val stickyKeysIndicatorCoordinator: Lazy<StickyKeysIndicatorCoordinator>, private val featureFlags: FeatureFlags, ) : CoreStartable { override fun start() { if (featureFlags.isEnabled(Flags.KEYBOARD_BACKLIGHT_INDICATOR)) { - keyboardBacklightDialogCoordinator.startListening() + keyboardBacklightDialogCoordinator.get().startListening() + } + if (keyboardA11yStickyKeysFlag()) { + stickyKeysIndicatorCoordinator.get().startListening() } } } diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/stickykeys/StickyKeysLogger.kt b/packages/SystemUI/src/com/android/systemui/keyboard/stickykeys/StickyKeysLogger.kt index 37034f63aca7..4ed812010100 100644 --- a/packages/SystemUI/src/com/android/systemui/keyboard/stickykeys/StickyKeysLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/keyboard/stickykeys/StickyKeysLogger.kt @@ -26,11 +26,20 @@ import javax.inject.Inject private const val TAG = "stickyKeys" class StickyKeysLogger @Inject constructor(@KeyboardLog private val buffer: LogBuffer) { - fun logNewStickyKeysReceived(linkedHashMap: Map<ModifierKey, Locked>) { + fun logNewStickyKeysReceived(stickyKeys: Map<ModifierKey, Locked>) { buffer.log( TAG, LogLevel.VERBOSE, - { str1 = linkedHashMap.toString() }, + { str1 = stickyKeys.toString() }, + { "new sticky keys state received: $str1" } + ) + } + + fun logNewUiState(stickyKeys: Map<ModifierKey, Locked>) { + buffer.log( + TAG, + LogLevel.INFO, + { str1 = stickyKeys.toString() }, { "new sticky keys state received: $str1" } ) } diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/stickykeys/ui/StickyKeysIndicatorCoordinator.kt b/packages/SystemUI/src/com/android/systemui/keyboard/stickykeys/ui/StickyKeysIndicatorCoordinator.kt new file mode 100644 index 000000000000..b68551bf93b3 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/keyboard/stickykeys/ui/StickyKeysIndicatorCoordinator.kt @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.keyboard.stickykeys.ui + +import android.app.Dialog +import android.util.Log +import android.view.Gravity +import android.view.ViewGroup.LayoutParams.WRAP_CONTENT +import android.view.Window +import android.view.WindowManager +import com.android.systemui.compose.ComposeFacade +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.dagger.qualifiers.Application +import com.android.systemui.keyboard.stickykeys.StickyKeysLogger +import com.android.systemui.keyboard.stickykeys.ui.viewmodel.StickyKeysIndicatorViewModel +import com.android.systemui.statusbar.phone.SystemUIDialogFactory +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch +import javax.inject.Inject + +@SysUISingleton +class StickyKeysIndicatorCoordinator +@Inject +constructor( + @Application private val applicationScope: CoroutineScope, + private val dialogFactory: SystemUIDialogFactory, + private val viewModel: StickyKeysIndicatorViewModel, + private val stickyKeysLogger: StickyKeysLogger, +) { + + private var dialog: Dialog? = null + + fun startListening() { + // this check needs to be moved to PhysicalKeyboardCoreStartable + if (!ComposeFacade.isComposeAvailable()) { + Log.e("StickyKeysIndicatorCoordinator", "Compose is required for this UI") + return + } + applicationScope.launch { + viewModel.indicatorContent.collect { stickyKeys -> + stickyKeysLogger.logNewUiState(stickyKeys) + if (stickyKeys.isEmpty()) { + dialog?.dismiss() + dialog = null + } else if (dialog == null) { + dialog = ComposeFacade.createStickyKeysDialog(dialogFactory, viewModel).apply { + setCanceledOnTouchOutside(false) + window?.setAttributes() + show() + } + } + } + } + } + + private fun Window.setAttributes() { + setType(WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL) + addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED) + clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND) + setGravity(Gravity.TOP or Gravity.END) + attributes = WindowManager.LayoutParams().apply { + copyFrom(attributes) + width = WRAP_CONTENT + title = "StickyKeysIndicator" + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index 5cebd96249b6..50caf17f71dd 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -2507,8 +2507,18 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, String message = ""; switch (msg.what) { case SHOW: - message = "SHOW"; - handleShow((Bundle) msg.obj); + // There is a potential race condition when SysUI starts up. CentralSurfaces + // must invoke #registerCentralSurfaces on this class before any messages can be + // processed. If this happens, repost the message with a small delay and try + // again. + if (mCentralSurfaces == null) { + message = "DELAYING SHOW"; + Message newMsg = mHandler.obtainMessage(SHOW, (Bundle) msg.obj); + mHandler.sendMessageDelayed(newMsg, 100); + } else { + message = "SHOW"; + handleShow((Bundle) msg.obj); + } break; case HIDE: message = "HIDE"; @@ -2595,8 +2605,18 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, Trace.endSection(); break; case SYSTEM_READY: - message = "SYSTEM_READY"; - handleSystemReady(); + // There is a potential race condition when SysUI starts up. CentralSurfaces + // must invoke #registerCentralSurfaces on this class before any messages can be + // processed. If this happens, repost the message with a small delay and try + // again. + if (mCentralSurfaces == null) { + message = "DELAYING SYSTEM_READY"; + Message newMsg = mHandler.obtainMessage(SYSTEM_READY); + mHandler.sendMessageDelayed(newMsg, 100); + } else { + message = "SYSTEM_READY"; + handleSystemReady(); + } break; } Log.d(TAG, "KeyguardViewMediator queue processing message: " + message); diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt index d012d24b767e..14371949c9c8 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt @@ -132,6 +132,9 @@ interface KeyguardRepository { */ val isDozing: StateFlow<Boolean> + /** Keyguard can be clipped at the top as the shade is dragged */ + val topClippingBounds: MutableStateFlow<Int?> + /** * Observable for whether the device is dreaming. * @@ -326,6 +329,8 @@ constructor( private val _clockShouldBeCentered = MutableStateFlow(true) override val clockShouldBeCentered: Flow<Boolean> = _clockShouldBeCentered.asStateFlow() + override val topClippingBounds = MutableStateFlow<Int?>(null) + override val isKeyguardShowing: Flow<Boolean> = conflatedCallbackFlow { val callback = diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt index 7b1466cd1fc9..a97c152ba7e3 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt @@ -17,14 +17,14 @@ package com.android.systemui.keyguard.domain.interactor import android.animation.ValueAnimator +import com.android.systemui.communal.domain.interactor.CommunalInteractor import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.power.domain.interactor.PowerInteractor -import com.android.systemui.util.kotlin.Utils.Companion.toQuad -import com.android.systemui.util.kotlin.Utils.Companion.toQuint +import com.android.systemui.util.kotlin.Utils.Companion.sample import com.android.systemui.util.kotlin.sample import com.android.wm.shell.animation.Interpolators import javax.inject.Inject @@ -32,7 +32,6 @@ import kotlin.time.Duration.Companion.milliseconds import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.delay -import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch @@ -46,6 +45,7 @@ constructor( @Background bgDispatcher: CoroutineDispatcher, @Main mainDispatcher: CoroutineDispatcher, private val keyguardInteractor: KeyguardInteractor, + private val communalInteractor: CommunalInteractor, private val powerInteractor: PowerInteractor, ) : TransitionInteractor( @@ -57,12 +57,12 @@ constructor( override fun start() { listenForAlternateBouncerToGone() - listenForAlternateBouncerToLockscreenAodOrDozing() + listenForAlternateBouncerToLockscreenHubAodOrDozing() listenForAlternateBouncerToPrimaryBouncer() listenForTransitionToCamera(scope, keyguardInteractor) } - private fun listenForAlternateBouncerToLockscreenAodOrDozing() { + private fun listenForAlternateBouncerToLockscreenHubAodOrDozing() { scope.launch { keyguardInteractor.alternateBouncerShowing // Add a slight delay, as alternateBouncer and primaryBouncer showing event changes @@ -70,14 +70,11 @@ constructor( // happening prematurely. .onEach { delay(50) } .sample( - combine( - keyguardInteractor.primaryBouncerShowing, - startedKeyguardTransitionStep, - powerInteractor.isAwake, - keyguardInteractor.isAodAvailable, - ::toQuad - ), - ::toQuint + keyguardInteractor.primaryBouncerShowing, + startedKeyguardTransitionStep, + powerInteractor.isAwake, + keyguardInteractor.isAodAvailable, + communalInteractor.isIdleOnCommunal ) .collect { ( @@ -85,7 +82,8 @@ constructor( isPrimaryBouncerShowing, lastStartedTransitionStep, isAwake, - isAodAvailable) -> + isAodAvailable, + isIdleOnCommunal) -> if ( !isAlternateBouncerShowing && !isPrimaryBouncerShowing && @@ -99,7 +97,11 @@ constructor( KeyguardState.DOZING } } else { - KeyguardState.LOCKSCREEN + if (isIdleOnCommunal) { + KeyguardState.GLANCEABLE_HUB + } else { + KeyguardState.LOCKSCREEN + } } startTransitionTo(to) } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt index fcb7698c9bf5..e2a8b6c53daa 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt @@ -18,6 +18,7 @@ package com.android.systemui.keyguard.domain.interactor import android.animation.ValueAnimator import com.android.app.animation.Interpolators +import com.android.systemui.communal.domain.interactor.CommunalInteractor import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dagger.qualifiers.Main @@ -25,7 +26,7 @@ import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepositor import com.android.systemui.keyguard.shared.model.BiometricUnlockModel.Companion.isWakeAndUnlock import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.power.domain.interactor.PowerInteractor -import com.android.systemui.util.kotlin.Utils.Companion.toTriple +import com.android.systemui.util.kotlin.Utils.Companion.toQuad import com.android.systemui.util.kotlin.sample import javax.inject.Inject import kotlin.time.Duration.Companion.milliseconds @@ -45,6 +46,7 @@ constructor( @Main mainDispatcher: CoroutineDispatcher, private val keyguardInteractor: KeyguardInteractor, private val powerInteractor: PowerInteractor, + private val communalInteractor: CommunalInteractor, ) : TransitionInteractor( fromState = KeyguardState.DOZING, @@ -54,26 +56,33 @@ constructor( ) { override fun start() { - listenForDozingToLockscreenOrOccluded() + listenForDozingToLockscreenHubOrOccluded() listenForDozingToGone() listenForTransitionToCamera(scope, keyguardInteractor) } - private fun listenForDozingToLockscreenOrOccluded() { + private fun listenForDozingToLockscreenHubOrOccluded() { scope.launch { powerInteractor.isAwake .sample( combine( startedKeyguardTransitionStep, keyguardInteractor.isKeyguardOccluded, - ::Pair + communalInteractor.isIdleOnCommunal, + ::Triple ), - ::toTriple + ::toQuad ) - .collect { (isAwake, lastStartedTransition, occluded) -> + .collect { (isAwake, lastStartedTransition, occluded, isIdleOnCommunal) -> if (isAwake && lastStartedTransition.to == KeyguardState.DOZING) { startTransitionTo( - if (occluded) KeyguardState.OCCLUDED else KeyguardState.LOCKSCREEN + if (occluded) { + KeyguardState.OCCLUDED + } else if (isIdleOnCommunal) { + KeyguardState.GLANCEABLE_HUB + } else { + KeyguardState.LOCKSCREEN + } ) } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt index 48b3d9acfe6a..9d6b30f9813d 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt @@ -18,6 +18,7 @@ package com.android.systemui.keyguard.domain.interactor import android.animation.ValueAnimator import com.android.app.animation.Interpolators +import com.android.app.tracing.coroutines.launch import com.android.systemui.Flags import com.android.systemui.communal.shared.model.CommunalSceneKey import com.android.systemui.dagger.SysUISingleton @@ -25,17 +26,25 @@ import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository import com.android.systemui.keyguard.shared.model.KeyguardState +import com.android.systemui.keyguard.shared.model.TransitionModeOnCanceled +import com.android.systemui.power.domain.interactor.PowerInteractor +import com.android.systemui.util.kotlin.sample import javax.inject.Inject import kotlin.time.Duration.Companion.milliseconds import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch @SysUISingleton class FromGlanceableHubTransitionInteractor @Inject constructor( + @Background private val scope: CoroutineScope, private val glanceableHubTransitions: GlanceableHubTransitions, + private val keyguardInteractor: KeyguardInteractor, override val transitionRepository: KeyguardTransitionRepository, transitionInteractor: KeyguardTransitionInteractor, + private val powerInteractor: PowerInteractor, @Main mainDispatcher: CoroutineDispatcher, @Background bgDispatcher: CoroutineDispatcher, ) : @@ -50,6 +59,9 @@ constructor( return } listenForHubToLockscreen() + listenForHubToDozing() + listenForHubToPrimaryBouncer() + listenForHubToAlternateBouncer() } override fun getDefaultAnimatorForTransitionsToState(toState: KeyguardState): ValueAnimator { @@ -67,12 +79,59 @@ constructor( glanceableHubTransitions.listenForLockscreenAndHubTransition( transitionName = "listenForHubToLockscreen", transitionOwnerName = TAG, - toScene = CommunalSceneKey.Blank + toScene = CommunalSceneKey.Blank, ) } + private fun listenForHubToPrimaryBouncer() { + scope.launch("$TAG#listenForHubToPrimaryBouncer") { + keyguardInteractor.primaryBouncerShowing + .sample(startedKeyguardTransitionStep, ::Pair) + .collect { pair -> + val (isBouncerShowing, lastStartedTransitionStep) = pair + if ( + isBouncerShowing && + lastStartedTransitionStep.to == KeyguardState.GLANCEABLE_HUB + ) { + startTransitionTo(KeyguardState.PRIMARY_BOUNCER) + } + } + } + } + + private fun listenForHubToAlternateBouncer() { + scope.launch("$TAG#listenForHubToAlternateBouncer") { + keyguardInteractor.alternateBouncerShowing + .sample(startedKeyguardTransitionStep, ::Pair) + .collect { pair -> + val (isAlternateBouncerShowing, lastStartedTransitionStep) = pair + if ( + isAlternateBouncerShowing && + lastStartedTransitionStep.to == KeyguardState.GLANCEABLE_HUB + ) { + startTransitionTo(KeyguardState.ALTERNATE_BOUNCER) + } + } + } + } + + private fun listenForHubToDozing() { + scope.launch { + powerInteractor.isAsleep.sample(startedKeyguardTransitionStep, ::Pair).collect { + (isAsleep, lastStartedStep) -> + if (lastStartedStep.to == fromState && isAsleep) { + startTransitionTo( + toState = KeyguardState.DOZING, + modeOnCanceled = TransitionModeOnCanceled.LAST_VALUE, + ) + } + } + } + } + companion object { const val TAG = "FromGlanceableHubTransitionInteractor" - val DEFAULT_DURATION = 500.milliseconds + val DEFAULT_DURATION = 400.milliseconds + val TO_LOCKSCREEN_DURATION = DEFAULT_DURATION } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt index c62055f83517..33b6373d5876 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt @@ -18,6 +18,7 @@ package com.android.systemui.keyguard.domain.interactor import android.animation.ValueAnimator import com.android.keyguard.KeyguardSecurityModel +import com.android.systemui.communal.domain.interactor.CommunalInteractor import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dagger.qualifiers.Main @@ -29,8 +30,8 @@ import com.android.systemui.keyguard.shared.model.KeyguardSurfaceBehindModel import com.android.systemui.keyguard.shared.model.TransitionModeOnCanceled import com.android.systemui.power.domain.interactor.PowerInteractor import com.android.systemui.user.domain.interactor.SelectedUserInteractor +import com.android.systemui.util.kotlin.Utils.Companion.sample import com.android.systemui.util.kotlin.Utils.Companion.toQuad -import com.android.systemui.util.kotlin.Utils.Companion.toQuint import com.android.systemui.util.kotlin.Utils.Companion.toTriple import com.android.systemui.util.kotlin.sample import com.android.wm.shell.animation.Interpolators @@ -54,6 +55,7 @@ constructor( @Background bgDispatcher: CoroutineDispatcher, @Main mainDispatcher: CoroutineDispatcher, private val keyguardInteractor: KeyguardInteractor, + private val communalInteractor: CommunalInteractor, private val flags: FeatureFlags, private val keyguardSecurityModel: KeyguardSecurityModel, private val selectedUserInteractor: SelectedUserInteractor, @@ -69,7 +71,7 @@ constructor( override fun start() { listenForPrimaryBouncerToGone() listenForPrimaryBouncerToAodOrDozing() - listenForPrimaryBouncerToLockscreenOrOccluded() + listenForPrimaryBouncerToLockscreenHubOrOccluded() listenForPrimaryBouncerToDreamingLockscreenHosted() listenForTransitionToCamera(scope, keyguardInteractor) } @@ -125,18 +127,15 @@ constructor( scope.launch { startTransitionTo(KeyguardState.GONE) } } - private fun listenForPrimaryBouncerToLockscreenOrOccluded() { + private fun listenForPrimaryBouncerToLockscreenHubOrOccluded() { scope.launch { keyguardInteractor.primaryBouncerShowing .sample( - combine( - powerInteractor.isAwake, - startedKeyguardTransitionStep, - keyguardInteractor.isKeyguardOccluded, - keyguardInteractor.isActiveDreamLockscreenHosted, - ::toQuad - ), - ::toQuint + powerInteractor.isAwake, + startedKeyguardTransitionStep, + keyguardInteractor.isKeyguardOccluded, + keyguardInteractor.isActiveDreamLockscreenHosted, + communalInteractor.isIdleOnCommunal ) .collect { ( @@ -144,16 +143,23 @@ constructor( isAwake, lastStartedTransitionStep, occluded, - isActiveDreamLockscreenHosted) -> + isActiveDreamLockscreenHosted, + isIdleOnCommunal) -> if ( !isBouncerShowing && lastStartedTransitionStep.to == KeyguardState.PRIMARY_BOUNCER && isAwake && !isActiveDreamLockscreenHosted ) { - startTransitionTo( - if (occluded) KeyguardState.OCCLUDED else KeyguardState.LOCKSCREEN - ) + val toState = + if (occluded) { + KeyguardState.OCCLUDED + } else if (isIdleOnCommunal) { + KeyguardState.GLANCEABLE_HUB + } else { + KeyguardState.LOCKSCREEN + } + startTransitionTo(toState) } } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/GlanceableHubTransitions.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/GlanceableHubTransitions.kt index cb50839331a2..ca661536d988 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/GlanceableHubTransitions.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/GlanceableHubTransitions.kt @@ -23,6 +23,7 @@ import com.android.systemui.communal.domain.interactor.CommunalInteractor import com.android.systemui.communal.domain.interactor.CommunalTransitionProgress import com.android.systemui.communal.shared.model.CommunalSceneKey import com.android.systemui.dagger.qualifiers.Application +import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.shared.model.TransitionInfo @@ -30,12 +31,15 @@ import com.android.systemui.keyguard.shared.model.TransitionState import com.android.systemui.util.kotlin.sample import java.util.UUID import javax.inject.Inject +import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.flowOn class GlanceableHubTransitions @Inject constructor( @Application private val scope: CoroutineScope, + @Background private val bgDispatcher: CoroutineDispatcher, private val transitionInteractor: KeyguardTransitionInteractor, private val transitionRepository: KeyguardTransitionRepository, private val communalInteractor: CommunalInteractor, @@ -66,7 +70,10 @@ constructor( scope.launch("$transitionOwnerName#$transitionName") { communalInteractor .transitionProgressToScene(toScene) - .sample(transitionInteractor.startedKeyguardTransitionStep, ::Pair) + .sample( + transitionInteractor.startedKeyguardTransitionStep.flowOn(bgDispatcher), + ::Pair + ) .collect { pair -> val (transitionProgress, lastStartedStep) = pair diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt index 6170356d4a90..91747e0f69a0 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt @@ -171,6 +171,14 @@ constructor( /** Whether the keyguard is going away. */ val isKeyguardGoingAway: Flow<Boolean> = repository.isKeyguardGoingAway + /** Keyguard can be clipped at the top as the shade is dragged */ + val topClippingBounds: Flow<Int?> = + combine(configurationInteractor.onAnyConfigurationChange, repository.topClippingBounds) { + _, + topClippingBounds -> + topClippingBounds + } + /** Last point that [KeyguardRootView] view was tapped */ val lastRootViewTapPosition: Flow<Point?> = repository.lastRootViewTapPosition.asStateFlow() @@ -328,6 +336,10 @@ constructor( repository.keyguardDoneAnimationsFinished() } + fun setTopClippingBounds(top: Int?) { + repository.topClippingBounds.value = top + } + companion object { private const val TAG = "KeyguardInteractor" } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt index 2aebd99e3664..48092c6374e0 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt @@ -21,6 +21,7 @@ import android.animation.AnimatorListenerAdapter import android.annotation.DrawableRes import android.annotation.SuppressLint import android.graphics.Point +import android.graphics.Rect import android.view.HapticFeedbackConstants import android.view.View import android.view.View.OnLayoutChangeListener @@ -158,6 +159,23 @@ object KeyguardRootViewBinder { } launch { + val clipBounds = Rect() + viewModel.topClippingBounds.collect { clipTop -> + if (clipTop == null) { + view.setClipBounds(null) + } else { + clipBounds.apply { + top = clipTop + left = view.getLeft() + right = view.getRight() + bottom = view.getBottom() + } + view.setClipBounds(clipBounds) + } + } + } + + launch { viewModel.lockscreenStateAlpha.collect { alpha -> childViews[statusViewId]?.alpha = alpha } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/KeyguardRootView.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/KeyguardRootView.kt index f33aed03856c..f2b28d964314 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/KeyguardRootView.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/KeyguardRootView.kt @@ -29,8 +29,4 @@ class KeyguardRootView( ConstraintLayout( context, attrs, - ) { - init { - clipChildren = false - } -} + ) diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToLockscreenTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToLockscreenTransitionViewModel.kt index bc518210a067..6aa2ecabae75 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToLockscreenTransitionViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/GlanceableHubToLockscreenTransitionViewModel.kt @@ -17,7 +17,7 @@ package com.android.systemui.keyguard.ui.viewmodel import com.android.systemui.dagger.SysUISingleton -import com.android.systemui.keyguard.domain.interactor.FromLockscreenTransitionInteractor +import com.android.systemui.keyguard.domain.interactor.FromGlanceableHubTransitionInteractor import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow import javax.inject.Inject @@ -37,7 +37,7 @@ constructor( ) { private val transitionAnimation = animationFlow.setup( - duration = FromLockscreenTransitionInteractor.TO_GLANCEABLE_HUB_DURATION, + duration = FromGlanceableHubTransitionInteractor.TO_LOCKSCREEN_DURATION, from = KeyguardState.GLANCEABLE_HUB, to = KeyguardState.LOCKSCREEN, ) @@ -45,10 +45,20 @@ constructor( // TODO(b/315205222): implement full animation spec instead of just a simple fade. val keyguardAlpha: Flow<Float> = transitionAnimation.sharedFlow( - duration = FromLockscreenTransitionInteractor.TO_GLANCEABLE_HUB_DURATION, + duration = FromGlanceableHubTransitionInteractor.TO_LOCKSCREEN_DURATION, onStep = { it }, onFinish = { 1f }, onCancel = { 0f }, name = "GLANCEABLE_HUB->LOCKSCREEN: keyguardAlpha", ) + + // TODO(b/315205216): implement full animation spec instead of just a simple fade. + val notificationAlpha: Flow<Float> = + transitionAnimation.sharedFlow( + duration = FromGlanceableHubTransitionInteractor.TO_LOCKSCREEN_DURATION, + onStep = { it }, + onFinish = { 1f }, + onCancel = { 0f }, + name = "GLANCEABLE_HUB->LOCKSCREEN: notificationAlpha", + ) } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt index 5d36da9b9df1..709e184e6e52 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt @@ -21,6 +21,7 @@ import android.graphics.Point import android.view.View.VISIBLE import com.android.systemui.Flags.newAodTransition import com.android.systemui.common.shared.model.NotificationContainerBounds +import com.android.systemui.communal.domain.interactor.CommunalInteractor import com.android.systemui.dagger.SysUISingleton import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor @@ -56,6 +57,7 @@ constructor( private val deviceEntryInteractor: DeviceEntryInteractor, private val dozeParameters: DozeParameters, private val keyguardInteractor: KeyguardInteractor, + communalInteractor: CommunalInteractor, keyguardTransitionInteractor: KeyguardTransitionInteractor, private val notificationsKeyguardInteractor: NotificationsKeyguardInteractor, aodToLockscreenTransitionViewModel: AodToLockscreenTransitionViewModel, @@ -80,13 +82,31 @@ constructor( val notificationBounds: StateFlow<NotificationContainerBounds> = keyguardInteractor.notificationContainerBounds + /** + * The keyguard root view can be clipped as the shade is pulled down, typically only for + * non-split shade cases. + */ + val topClippingBounds: Flow<Int?> = keyguardInteractor.topClippingBounds + /** An observable for the alpha level for the entire keyguard root view. */ val alpha: Flow<Float> = - merge( - aodAlphaViewModel.alpha, - lockscreenToGlanceableHubTransitionViewModel.keyguardAlpha, - glanceableHubToLockscreenTransitionViewModel.keyguardAlpha, - ) + combine( + communalInteractor.isIdleOnCommunal, + merge( + aodAlphaViewModel.alpha, + lockscreenToGlanceableHubTransitionViewModel.keyguardAlpha, + glanceableHubToLockscreenTransitionViewModel.keyguardAlpha, + ) + ) { isIdleOnCommunal, alpha -> + if (isIdleOnCommunal) { + // Keyguard should not show while the communal hub is fully visible. This check + // is added since at the moment, closing the notification shade will cause the + // keyguard alpha to be set back to 1. + 0f + } else { + alpha + } + } .distinctUntilChanged() /** Specific alpha value for elements visible during [KeyguardState.LOCKSCREEN] */ diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGlanceableHubTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGlanceableHubTransitionViewModel.kt index 3ea83ae21085..3afa49e50167 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGlanceableHubTransitionViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToGlanceableHubTransitionViewModel.kt @@ -51,4 +51,14 @@ constructor( onCancel = { 1f }, name = "LOCKSCREEN->GLANCEABLE_HUB: keyguardAlpha", ) + + // TODO(b/315205216): implement full animation spec instead of just a simple fade. + val notificationAlpha: Flow<Float> = + transitionAnimation.sharedFlow( + duration = FromLockscreenTransitionInteractor.TO_GLANCEABLE_HUB_DURATION, + onStep = { 1f - it }, + onFinish = { 0f }, + onCancel = { 1f }, + name = "LOCKSCREEN->GLANCEABLE_HUB: notificationAlpha", + ) } diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHost.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHost.kt index 631a0b8471b8..437218f9f440 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHost.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHost.kt @@ -228,6 +228,14 @@ constructor( } } + override var expandedMatchesParentHeight: Boolean = false + set(value) { + if (value != field) { + field = value + changedListener?.invoke() + } + } + override var squishFraction: Float = 1.0f set(value) { if (!value.equals(field)) { @@ -282,6 +290,7 @@ constructor( override fun copy(): MediaHostState { val mediaHostState = MediaHostStateHolder() mediaHostState.expansion = expansion + mediaHostState.expandedMatchesParentHeight = expandedMatchesParentHeight mediaHostState.squishFraction = squishFraction mediaHostState.showsOnlyActiveMedia = showsOnlyActiveMedia mediaHostState.measurementInput = measurementInput?.copy() @@ -360,6 +369,12 @@ interface MediaHostState { */ var expansion: Float + /** + * If true, the [EXPANDED] layout should stretch to match the height of its parent container, + * rather than having a fixed height. + */ + var expandedMatchesParentHeight: Boolean + /** Fraction of the height animation. */ var squishFraction: Float diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaViewController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaViewController.kt index be9393655c5d..962764c028fc 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaViewController.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaViewController.kt @@ -20,6 +20,7 @@ import android.content.Context import android.content.res.Configuration import androidx.annotation.VisibleForTesting import androidx.constraintlayout.widget.ConstraintSet +import androidx.constraintlayout.widget.ConstraintSet.MATCH_CONSTRAINT import com.android.app.tracing.traceSection import com.android.systemui.media.controls.models.GutsViewHolder import com.android.systemui.media.controls.models.player.MediaViewHolder @@ -152,18 +153,11 @@ constructor( lastOrientation = newOrientation // Update the height of media controls for the expanded layout. it is needed // for large screen devices. - val backgroundIds = - if (type == TYPE.PLAYER) { - MediaViewHolder.backgroundIds - } else { - setOf(RecommendationViewHolder.backgroundId) - } - backgroundIds.forEach { id -> - expandedLayout.getConstraint(id).layout.mHeight = - context.resources.getDimensionPixelSize( - R.dimen.qs_media_session_height_expanded - ) - } + setBackgroundHeights( + context.resources.getDimensionPixelSize( + R.dimen.qs_media_session_height_expanded + ) + ) } if (this@MediaViewController::configurationChangeListener.isInitialized) { configurationChangeListener.invoke() @@ -276,6 +270,17 @@ constructor( private fun constraintSetForExpansion(expansion: Float): ConstraintSet = if (expansion > 0) expandedLayout else collapsedLayout + /** Set the height of UMO background constraints. */ + private fun setBackgroundHeights(height: Int) { + val backgroundIds = + if (type == TYPE.PLAYER) { + MediaViewHolder.backgroundIds + } else { + setOf(RecommendationViewHolder.backgroundId) + } + backgroundIds.forEach { id -> expandedLayout.getConstraint(id).layout.mHeight = height } + } + /** * Set the views to be showing/hidden based on the [isGutsVisible] for a given * [TransitionViewState]. @@ -454,6 +459,18 @@ constructor( } // Let's create a new measurement if (state.expansion == 0.0f || state.expansion == 1.0f) { + if (state.expansion == 1.0f) { + val height = + if (state.expandedMatchesParentHeight) { + MATCH_CONSTRAINT + } else { + context.resources.getDimensionPixelSize( + R.dimen.qs_media_session_height_expanded + ) + } + setBackgroundHeights(height) + } + result = transitionLayout!!.calculateViewState( state.measurementInput!!, diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java index 0a72a2f15e95..068e5fd61ea4 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java @@ -504,24 +504,6 @@ public class NavigationBar extends ViewController<NavigationBarView> implements } }; - private final ViewRootImpl.SurfaceChangedCallback mSurfaceChangedCallback = - new SurfaceChangedCallback() { - @Override - public void surfaceCreated(Transaction t) { - notifyNavigationBarSurface(); - } - - @Override - public void surfaceDestroyed() { - notifyNavigationBarSurface(); - } - - @Override - public void surfaceReplaced(Transaction t) { - notifyNavigationBarSurface(); - } - }; - private boolean mScreenPinningActive = false; private final TaskStackChangeListener mTaskStackListener = new TaskStackChangeListener() { @Override @@ -787,8 +769,6 @@ public class NavigationBar extends ViewController<NavigationBarView> implements mView.getViewTreeObserver().addOnComputeInternalInsetsListener( mOnComputeInternalInsetsListener); - mView.getViewRootImpl().addSurfaceChangedCallback(mSurfaceChangedCallback); - notifyNavigationBarSurface(); mPipOptional.ifPresent(mView::addPipExclusionBoundsChangeListener); mBackAnimation.ifPresent(mView::registerBackAnimation); @@ -860,13 +840,8 @@ public class NavigationBar extends ViewController<NavigationBarView> implements mHandler.removeCallbacks(mEnableLayoutTransitions); mNavBarHelper.removeNavTaskStateUpdater(mNavbarTaskbarStateUpdater); mPipOptional.ifPresent(mView::removePipExclusionBoundsChangeListener); - ViewRootImpl viewRoot = mView.getViewRootImpl(); - if (viewRoot != null) { - viewRoot.removeSurfaceChangedCallback(mSurfaceChangedCallback); - } mFrame = null; mOrientationHandle = null; - notifyNavigationBarSurface(); } // TODO: Remove this when we update nav bar recreation @@ -1026,17 +1001,6 @@ public class NavigationBar extends ViewController<NavigationBarView> implements } } - private void notifyNavigationBarSurface() { - ViewRootImpl viewRoot = mView.getViewRootImpl(); - SurfaceControl surface = mView.getParent() != null - && viewRoot != null - && viewRoot.getSurfaceControl() != null - && viewRoot.getSurfaceControl().isValid() - ? viewRoot.getSurfaceControl() - : null; - mOverviewProxyService.onNavigationBarSurfaceChanged(surface); - } - private int deltaRotation(int oldRotation, int newRotation) { int delta = newRotation - oldRotation; if (delta < 0) delta += 4; diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java index a3b92541d593..a2dfc0159c6e 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java @@ -27,8 +27,11 @@ import android.graphics.PointF; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; +import android.view.ViewGroup; import android.widget.FrameLayout; +import androidx.annotation.Nullable; + import com.android.systemui.Dumpable; import com.android.systemui.qs.customize.QSCustomizer; import com.android.systemui.res.R; @@ -53,6 +56,7 @@ public class QSContainerImpl extends FrameLayout implements Dumpable { private QuickStatusBarHeader mHeader; private float mQsExpansion; private QSCustomizer mQSCustomizer; + private QSPanel mQSPanel; private NonInterceptingScrollView mQSPanelContainer; private int mHorizontalMargins; @@ -72,6 +76,7 @@ public class QSContainerImpl extends FrameLayout implements Dumpable { protected void onFinishInflate() { super.onFinishInflate(); mQSPanelContainer = findViewById(R.id.expanded_qs_scroll_view); + mQSPanel = findViewById(R.id.quick_settings_panel); mHeader = findViewById(R.id.header); mQSCustomizer = findViewById(R.id.qs_customize); setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO); @@ -79,6 +84,13 @@ public class QSContainerImpl extends FrameLayout implements Dumpable { void setSceneContainerEnabled(boolean enabled) { mSceneContainerEnabled = enabled; + if (enabled) { + mQSPanelContainer.removeAllViews(); + removeView(mQSPanelContainer); + LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT); + addView(mQSPanel, 0, lp); + } } @Override @@ -97,20 +109,26 @@ public class QSContainerImpl extends FrameLayout implements Dumpable { protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // QSPanel will show as many rows as it can (up to TileLayout.MAX_ROWS) such that the // bottom and footer are inside the screen. - MarginLayoutParams layoutParams = (MarginLayoutParams) mQSPanelContainer.getLayoutParams(); - int availableHeight = View.MeasureSpec.getSize(heightMeasureSpec); - int maxQs = availableHeight - layoutParams.topMargin - layoutParams.bottomMargin - - getPaddingBottom(); - int padding = mPaddingLeft + mPaddingRight + layoutParams.leftMargin - + layoutParams.rightMargin; - final int qsPanelWidthSpec = getChildMeasureSpec(widthMeasureSpec, padding, - layoutParams.width); - mQSPanelContainer.measure(qsPanelWidthSpec, - MeasureSpec.makeMeasureSpec(maxQs, MeasureSpec.AT_MOST)); - int width = mQSPanelContainer.getMeasuredWidth() + padding; - super.onMeasure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), - MeasureSpec.makeMeasureSpec(availableHeight, MeasureSpec.EXACTLY)); + + if (!mSceneContainerEnabled) { + MarginLayoutParams layoutParams = + (MarginLayoutParams) mQSPanelContainer.getLayoutParams(); + int maxQs = availableHeight - layoutParams.topMargin - layoutParams.bottomMargin + - getPaddingBottom(); + int padding = mPaddingLeft + mPaddingRight + layoutParams.leftMargin + + layoutParams.rightMargin; + final int qsPanelWidthSpec = getChildMeasureSpec(widthMeasureSpec, padding, + layoutParams.width); + mQSPanelContainer.measure(qsPanelWidthSpec, + MeasureSpec.makeMeasureSpec(maxQs, MeasureSpec.AT_MOST)); + int width = mQSPanelContainer.getMeasuredWidth() + padding; + super.onMeasure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(availableHeight, MeasureSpec.EXACTLY)); + } else { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + // QSCustomizer will always be the height of the screen, but do this after // other measuring to avoid changing the height of the QS. mQSCustomizer.measure(widthMeasureSpec, @@ -130,12 +148,15 @@ public class QSContainerImpl extends FrameLayout implements Dumpable { @Override protected void measureChildWithMargins(View child, int parentWidthMeasureSpec, int widthUsed, int parentHeightMeasureSpec, int heightUsed) { - // Do not measure QSPanel again when doing super.onMeasure. - // This prevents the pages in PagedTileLayout to be remeasured with a different (incorrect) - // size to the one used for determining the number of rows and then the number of pages. - if (child != mQSPanelContainer) { - super.measureChildWithMargins(child, parentWidthMeasureSpec, widthUsed, - parentHeightMeasureSpec, heightUsed); + if (!mSceneContainerEnabled) { + // Do not measure QSPanel again when doing super.onMeasure. + // This prevents the pages in PagedTileLayout to be remeasured with a different + // (incorrect) size to the one used for determining the number of rows and then the + // number of pages. + if (child != mQSPanelContainer) { + super.measureChildWithMargins(child, parentWidthMeasureSpec, widthUsed, + parentHeightMeasureSpec, heightUsed); + } } } @@ -151,6 +172,7 @@ public class QSContainerImpl extends FrameLayout implements Dumpable { updateClippingPath(); } + @Nullable public NonInterceptingScrollView getQSPanelContainer() { return mQSPanelContainer; } @@ -172,11 +194,19 @@ public class QSContainerImpl extends FrameLayout implements Dumpable { .getDimensionPixelSize( R.dimen.large_screen_shade_header_height); } - mQSPanelContainer.setPaddingRelative( - mQSPanelContainer.getPaddingStart(), - mSceneContainerEnabled ? 0 : topPadding, - mQSPanelContainer.getPaddingEnd(), - mQSPanelContainer.getPaddingBottom()); + if (mQSPanelContainer != null) { + mQSPanelContainer.setPaddingRelative( + mQSPanelContainer.getPaddingStart(), + mSceneContainerEnabled ? 0 : topPadding, + mQSPanelContainer.getPaddingEnd(), + mQSPanelContainer.getPaddingBottom()); + } else { + mQSPanel.setPaddingRelative( + mQSPanel.getPaddingStart(), + mSceneContainerEnabled ? 0 : topPadding, + mQSPanel.getPaddingEnd(), + mQSPanel.getPaddingBottom()); + } int horizontalMargins = getResources().getDimensionPixelSize(R.dimen.qs_horizontal_margin); int horizontalPadding = getResources().getDimensionPixelSize( @@ -220,7 +250,9 @@ public class QSContainerImpl extends FrameLayout implements Dumpable { public void setExpansion(float expansion) { mQsExpansion = expansion; - mQSPanelContainer.setScrollingEnabled(expansion > 0f); + if (mQSPanelContainer != null) { + mQSPanelContainer.setScrollingEnabled(expansion > 0f); + } updateExpansion(); } @@ -239,7 +271,7 @@ public class QSContainerImpl extends FrameLayout implements Dumpable { lp.rightMargin = mHorizontalMargins; lp.leftMargin = mHorizontalMargins; } - if (view == mQSPanelContainer) { + if (view == mQSPanelContainer || view == mQSPanel) { // QS panel lays out some of its content full width qsPanelController.setContentMargins(mContentHorizontalPadding, mContentHorizontalPadding); diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImplController.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImplController.java index 7b001c7b72f7..ffbc56098e26 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImplController.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImplController.java @@ -81,6 +81,9 @@ public class QSContainerImplController extends ViewController<QSContainerImpl> { public void onInit() { mQuickStatusBarHeaderController.init(); mView.setSceneContainerEnabled(mSceneContainerEnabled); + if (mSceneContainerEnabled && mQsPanelController != null) { + mQSPanelContainer.setOnTouchListener(null); + } } public void setListening(boolean listening) { @@ -91,13 +94,17 @@ public class QSContainerImplController extends ViewController<QSContainerImpl> { protected void onViewAttached() { mView.updateResources(mQsPanelController, mQuickStatusBarHeaderController); mConfigurationController.addCallback(mConfigurationListener); - mQSPanelContainer.setOnTouchListener(mContainerTouchHandler); + if (!mSceneContainerEnabled && mQSPanelContainer != null) { + mQSPanelContainer.setOnTouchListener(mContainerTouchHandler); + } } @Override protected void onViewDetached() { mConfigurationController.removeCallback(mConfigurationListener); - mQSPanelContainer.setOnTouchListener(null); + if (mQSPanelContainer != null) { + mQSPanelContainer.setOnTouchListener(null); + } } public QSContainerImpl getView() { diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSImpl.java index 7f91fd2ebb80..290821e4ab13 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSImpl.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSImpl.java @@ -61,6 +61,7 @@ import com.android.systemui.qs.footer.ui.binder.FooterActionsViewBinder; import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.res.R; +import com.android.systemui.scene.shared.flag.SceneContainerFlags; import com.android.systemui.shade.transition.LargeScreenShadeInterpolator; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.StatusBarState; @@ -171,8 +172,11 @@ public class QSImpl implements QS, CommandQueue.Callbacks, StatusBarStateControl private CommandQueue mCommandQueue; private View mRootView; + @Nullable private View mFooterActionsView; + private final SceneContainerFlags mSceneContainerFlags; + @Inject public QSImpl(RemoteInputQuickSettingsDisabler remoteInputQsDisabler, SysuiStatusBarStateController statusBarStateController, CommandQueue commandQueue, @@ -185,7 +189,8 @@ public class QSImpl implements QS, CommandQueue.Callbacks, StatusBarStateControl FooterActionsViewModel.Factory footerActionsViewModelFactory, FooterActionsViewBinder footerActionsViewBinder, LargeScreenShadeInterpolator largeScreenShadeInterpolator, - FeatureFlags featureFlags) { + FeatureFlags featureFlags, + SceneContainerFlags sceneContainerFlags) { mRemoteInputQuickSettingsDisabler = remoteInputQsDisabler; mQsMediaHost = qsMediaHost; mQqsMediaHost = qqsMediaHost; @@ -201,6 +206,7 @@ public class QSImpl implements QS, CommandQueue.Callbacks, StatusBarStateControl mFooterActionsViewModelFactory = footerActionsViewModelFactory; mFooterActionsViewBinder = footerActionsViewBinder; mListeningAndVisibilityLifecycleOwner = new ListeningAndVisibilityLifecycleOwner(); + mSceneContainerFlags = sceneContainerFlags; } /** @@ -216,10 +222,17 @@ public class QSImpl implements QS, CommandQueue.Callbacks, StatusBarStateControl mQSPanelController.init(); mQuickQSPanelController.init(); - mQSFooterActionsViewModel = mFooterActionsViewModelFactory - .create(mListeningAndVisibilityLifecycleOwner); - bindFooterActionsView(mRootView); - mFooterActionsController.init(); + if (!mSceneContainerFlags.isEnabled()) { + mQSFooterActionsViewModel = mFooterActionsViewModelFactory + .create(mListeningAndVisibilityLifecycleOwner); + bindFooterActionsView(mRootView); + mFooterActionsController.init(); + } else { + View footerView = mRootView.findViewById(R.id.qs_footer_actions); + if (footerView != null) { + ((ViewGroup) footerView.getParent()).removeView(footerView); + } + } mQSPanelScrollView = mRootView.findViewById(R.id.expanded_qs_scroll_view); mQSPanelScrollView.addOnLayoutChangeListener( @@ -234,6 +247,7 @@ public class QSImpl implements QS, CommandQueue.Callbacks, StatusBarStateControl mScrollListener.onQsPanelScrollChanged(scrollY); } }); + mQSPanelScrollView.setScrollingEnabled(!mSceneContainerFlags.isEnabled()); mHeader = mRootView.findViewById(R.id.header); mFooter = qsComponent.getQSFooter(); @@ -481,7 +495,9 @@ public class QSImpl implements QS, CommandQueue.Callbacks, StatusBarStateControl boolean footerVisible = qsPanelVisible && (mQsExpanded || !keyguardShowing || mHeaderAnimating || mShowCollapsedOnKeyguard); mFooter.setVisibility(footerVisible ? View.VISIBLE : View.INVISIBLE); - mFooterActionsView.setVisibility(footerVisible ? View.VISIBLE : View.INVISIBLE); + if (mFooterActionsView != null) { + mFooterActionsView.setVisibility(footerVisible ? View.VISIBLE : View.INVISIBLE); + } mFooter.setExpanded((keyguardShowing && !mHeaderAnimating && !mShowCollapsedOnKeyguard) || (mQsExpanded && !mStackScrollerOverscrolling)); mQSPanelController.setVisibility(qsPanelVisible ? View.VISIBLE : View.INVISIBLE); @@ -622,8 +638,13 @@ public class QSImpl implements QS, CommandQueue.Callbacks, StatusBarStateControl @Override public int getHeightDiff() { - return mQSPanelScrollView.getBottom() - mHeader.getBottom() - + mHeader.getPaddingBottom(); + if (mSceneContainerFlags.isEnabled()) { + return mQSPanelController.getViewBottom() - mHeader.getBottom() + + mHeader.getPaddingBottom(); + } else { + return mQSPanelScrollView.getBottom() - mHeader.getBottom() + + mHeader.getPaddingBottom(); + } } @Override @@ -678,25 +699,29 @@ public class QSImpl implements QS, CommandQueue.Callbacks, StatusBarStateControl mFooter.setExpansion(onKeyguardAndExpanded ? 1 : expansion); float footerActionsExpansion = onKeyguardAndExpanded ? 1 : mInSplitShade ? alphaProgress : expansion; - mQSFooterActionsViewModel.onQuickSettingsExpansionChanged(footerActionsExpansion, - mInSplitShade); + if (mQSFooterActionsViewModel != null) { + mQSFooterActionsViewModel.onQuickSettingsExpansionChanged(footerActionsExpansion, + mInSplitShade); + } mQSPanelController.setRevealExpansion(expansion); mQSPanelController.getTileLayout().setExpansion(expansion, proposedTranslation); mQuickQSPanelController.getTileLayout().setExpansion(expansion, proposedTranslation); - float qsScrollViewTranslation = - onKeyguard && !mShowCollapsedOnKeyguard ? panelTranslationY : 0; - mQSPanelScrollView.setTranslationY(qsScrollViewTranslation); + if (!mSceneContainerFlags.isEnabled()) { + float qsScrollViewTranslation = + onKeyguard && !mShowCollapsedOnKeyguard ? panelTranslationY : 0; + mQSPanelScrollView.setTranslationY(qsScrollViewTranslation); - if (fullyCollapsed) { - mQSPanelScrollView.setScrollY(0); - } + if (fullyCollapsed) { + mQSPanelScrollView.setScrollY(0); + } - if (!fullyExpanded) { - // Set bounds on the QS panel so it doesn't run over the header when animating. - mQsBounds.top = (int) -mQSPanelScrollView.getTranslationY(); - mQsBounds.right = mQSPanelScrollView.getWidth(); - mQsBounds.bottom = mQSPanelScrollView.getHeight(); + if (!fullyExpanded) { + // Set bounds on the QS panel so it doesn't run over the header when animating. + mQsBounds.top = (int) -mQSPanelScrollView.getTranslationY(); + mQsBounds.right = mQSPanelScrollView.getWidth(); + mQsBounds.bottom = mQSPanelScrollView.getHeight(); + } } updateQsBounds(); @@ -786,15 +811,17 @@ public class QSImpl implements QS, CommandQueue.Callbacks, StatusBarStateControl mQsBounds.set(-sideMargin, 0, mQSPanelScrollView.getWidth() + sideMargin, mQSPanelScrollView.getHeight()); } - mQSPanelScrollView.setClipBounds(mQsBounds); - - mQSPanelScrollView.getLocationOnScreen(mLocationTemp); - int left = mLocationTemp[0]; - int top = mLocationTemp[1]; - mQsMediaHost.getCurrentClipping().set(left, top, - left + getView().getMeasuredWidth(), - top + mQSPanelScrollView.getMeasuredHeight() - - mQSPanelController.getPaddingBottom()); + if (!mSceneContainerFlags.isEnabled()) { + mQSPanelScrollView.setClipBounds(mQsBounds); + + mQSPanelScrollView.getLocationOnScreen(mLocationTemp); + int left = mLocationTemp[0]; + int top = mLocationTemp[1]; + mQsMediaHost.getCurrentClipping().set(left, top, + left + getView().getMeasuredWidth(), + top + mQSPanelScrollView.getMeasuredHeight() + - mQSPanelController.getPaddingBottom()); + } } private void updateMediaPositions() { @@ -867,9 +894,15 @@ public class QSImpl implements QS, CommandQueue.Callbacks, StatusBarStateControl // The customize state changed, so our height changed. mContainer.updateExpansion(); boolean customizing = isCustomizing(); - mQSPanelScrollView.setVisibility(!customizing ? View.VISIBLE : View.INVISIBLE); + if (mSceneContainerFlags.isEnabled()) { + mQSPanelController.setVisibility(!customizing ? View.VISIBLE : View.INVISIBLE); + } else { + mQSPanelScrollView.setVisibility(!customizing ? View.VISIBLE : View.INVISIBLE); + } mFooter.setVisibility(!customizing ? View.VISIBLE : View.INVISIBLE); - mFooterActionsView.setVisibility(!customizing ? View.VISIBLE : View.INVISIBLE); + if (mFooterActionsView != null) { + mFooterActionsView.setVisibility(!customizing ? View.VISIBLE : View.INVISIBLE); + } mHeader.setVisibility(!customizing ? View.VISIBLE : View.INVISIBLE); // Let the panel know the position changed and it needs to update where notifications // and whatnot are. diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java index 51b94dd983f3..7a7ee59fa63f 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java @@ -387,7 +387,7 @@ public class QSPanel extends LinearLayout implements Tunable { setPaddingRelative(getPaddingStart(), mSceneContainerEnabled ? 0 : paddingTop, getPaddingEnd(), - paddingBottom); + mSceneContainerEnabled ? 0 : paddingBottom); } void addOnConfigurationChangedListener(OnConfigurationChangedListener listener) { diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java index ef58a608aa1f..c3f5086b0096 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java @@ -278,5 +278,9 @@ public class QSPanelController extends QSPanelControllerBase<QSPanel> { public int getPaddingBottom() { return mView.getPaddingBottom(); } + + int getViewBottom() { + return mView.getBottom(); + } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java index a103566400a6..07705f361881 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java +++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java @@ -58,6 +58,7 @@ public class QSCustomizer extends LinearLayout { private final RecyclerView mRecyclerView; private boolean mCustomizing; private QSContainerController mQsContainerController; + private final Toolbar mToolbar; private QS mQs; private int mX; private int mY; @@ -69,15 +70,15 @@ public class QSCustomizer extends LinearLayout { LayoutInflater.from(getContext()).inflate(R.layout.qs_customize_panel_content, this); mClipper = new QSDetailClipper(findViewById(R.id.customize_container)); - Toolbar toolbar = findViewById(com.android.internal.R.id.action_bar); + mToolbar = findViewById(com.android.internal.R.id.action_bar); TypedValue value = new TypedValue(); mContext.getTheme().resolveAttribute(android.R.attr.homeAsUpIndicator, value, true); - toolbar.setNavigationIcon( + mToolbar.setNavigationIcon( getResources().getDrawable(value.resourceId, mContext.getTheme())); - toolbar.getMenu().add(Menu.NONE, MENU_RESET, 0, com.android.internal.R.string.reset) + mToolbar.getMenu().add(Menu.NONE, MENU_RESET, 0, com.android.internal.R.string.reset) .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); - toolbar.setTitle(R.string.qs_edit); + mToolbar.setTitle(R.string.qs_edit); mRecyclerView = findViewById(android.R.id.list); mTransparentView = findViewById(R.id.customizer_transparent_view); DefaultItemAnimator animator = new DefaultItemAnimator(); @@ -184,6 +185,14 @@ public class QSCustomizer extends LinearLayout { return isShown; } + @Override + protected void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + mToolbar.setTitleTextAppearance(mContext, + android.R.style.TextAppearance_DeviceDefault_Widget_ActionBar_Title); + updateToolbarMenuFontSize(); + } + void setCustomizing(boolean customizing) { mCustomizing = customizing; if (mQs != null) { @@ -269,4 +278,11 @@ public class QSCustomizer extends LinearLayout { lp.height = QSUtils.getQsHeaderSystemIconsAreaHeight(mContext); mTransparentView.setLayoutParams(lp); } + + private void updateToolbarMenuFontSize() { + // Clearing and re-adding the toolbar action force updates the font size + mToolbar.getMenu().clear(); + mToolbar.getMenu().add(Menu.NONE, MENU_RESET, 0, com.android.internal.R.string.reset) + .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); + } }
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt index 456520051f58..c5eeb2f87d3a 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt @@ -249,6 +249,10 @@ open class QSTileViewImpl @JvmOverloads constructor( height = iconSize marginEnd = endMargin } + + background = createTileBackground() + setColor(backgroundColor) + setOverlayColor(backgroundOverlayColor) } private fun createAndAddLabels() { diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java index 3a247c5843d4..3b8fb263c27e 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java @@ -20,6 +20,7 @@ import static android.graphics.drawable.Icon.TYPE_URI; import static android.provider.Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT; import static com.android.systemui.wallet.controller.QuickAccessWalletController.WalletChangeEvent.DEFAULT_PAYMENT_APP_CHANGE; +import static com.android.systemui.wallet.controller.QuickAccessWalletController.WalletChangeEvent.DEFAULT_WALLET_APP_CHANGE; import static com.android.systemui.wallet.util.WalletCardUtilsKt.getPaymentCards; import android.content.Intent; @@ -42,7 +43,6 @@ import androidx.annotation.Nullable; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.jank.InteractionJankMonitor; import com.android.internal.logging.MetricsLogger; -import com.android.systemui.res.R; import com.android.systemui.animation.ActivityLaunchAnimator; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; @@ -54,6 +54,7 @@ import com.android.systemui.qs.QSHost; import com.android.systemui.qs.QsEventLogger; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; +import com.android.systemui.res.R; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.util.settings.SecureSettings; import com.android.systemui.wallet.controller.QuickAccessWalletController; @@ -118,7 +119,8 @@ public class QuickAccessWalletTile extends QSTileImpl<QSTile.State> { protected void handleSetListening(boolean listening) { super.handleSetListening(listening); if (listening) { - mController.setupWalletChangeObservers(mCardRetriever, DEFAULT_PAYMENT_APP_CHANGE); + mController.setupWalletChangeObservers(mCardRetriever, DEFAULT_PAYMENT_APP_CHANGE, + DEFAULT_WALLET_APP_CHANGE); if (!mController.getWalletClient().isWalletServiceAvailable() || !mController.getWalletClient().isWalletFeatureAvailable()) { Log.i(TAG, "QAW service is unavailable, recreating the wallet client."); @@ -201,7 +203,8 @@ public class QuickAccessWalletTile extends QSTileImpl<QSTile.State> { @Override protected void handleDestroy() { super.handleDestroy(); - mController.unregisterWalletChangeObservers(DEFAULT_PAYMENT_APP_CHANGE); + mController.unregisterWalletChangeObservers(DEFAULT_PAYMENT_APP_CHANGE, + DEFAULT_WALLET_APP_CHANGE); } private class WalletCardRetriever implements diff --git a/packages/SystemUI/src/com/android/systemui/qs/ui/adapter/QSSceneAdapter.kt b/packages/SystemUI/src/com/android/systemui/qs/ui/adapter/QSSceneAdapter.kt index ce840eec29d9..0d4339680dac 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/ui/adapter/QSSceneAdapter.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/ui/adapter/QSSceneAdapter.kt @@ -17,10 +17,13 @@ package com.android.systemui.qs.ui.adapter import android.content.Context +import android.content.pm.ActivityInfo import android.os.Bundle import android.view.View import androidx.annotation.VisibleForTesting import androidx.asynclayoutinflater.view.AsyncLayoutInflater +import com.android.settingslib.applications.InterestingConfigChanges +import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Main @@ -58,7 +61,7 @@ interface QSSceneAdapter { /** * Inflate an instance of [QSImpl] for this context. Once inflated, it will be available in - * [qsView] + * [qsView]. Re-inflations due to configuration changes will use the last used [context]. */ suspend fun inflate(context: Context) @@ -90,6 +93,7 @@ constructor( private val qsImplProvider: Provider<QSImpl>, @Main private val mainDispatcher: CoroutineDispatcher, @Application applicationScope: CoroutineScope, + private val configurationInteractor: ConfigurationInteractor, private val asyncLayoutInflaterFactory: (Context) -> AsyncLayoutInflater, ) : QSContainerController, QSSceneAdapter { @@ -99,7 +103,15 @@ constructor( qsImplProvider: Provider<QSImpl>, @Main dispatcher: CoroutineDispatcher, @Application scope: CoroutineScope, - ) : this(qsSceneComponentFactory, qsImplProvider, dispatcher, scope, ::AsyncLayoutInflater) + configurationInteractor: ConfigurationInteractor, + ) : this( + qsSceneComponentFactory, + qsImplProvider, + dispatcher, + scope, + configurationInteractor, + ::AsyncLayoutInflater, + ) private val state = MutableStateFlow<QSSceneAdapter.State>(QSSceneAdapter.State.CLOSED) private val _isCustomizing: MutableStateFlow<Boolean> = MutableStateFlow(false) @@ -109,14 +121,36 @@ constructor( val qsImpl = _qsImpl.asStateFlow() override val qsView: Flow<View> = _qsImpl.map { it?.view }.filterNotNull() + // Same config changes as in FragmentHostManager + private val interestingChanges = + InterestingConfigChanges( + ActivityInfo.CONFIG_FONT_SCALE or + ActivityInfo.CONFIG_LOCALE or + ActivityInfo.CONFIG_ASSETS_PATHS + ) + init { applicationScope.launch { - state.sample(_isCustomizing, ::Pair).collect { (state, customizing) -> - _qsImpl.value?.apply { - if (state != QSSceneAdapter.State.QS && customizing) { - this@apply.closeCustomizerImmediately() + launch { + state.sample(_isCustomizing, ::Pair).collect { (state, customizing) -> + _qsImpl.value?.apply { + if (state != QSSceneAdapter.State.QS && customizing) { + this@apply.closeCustomizerImmediately() + } + applyState(state) + } + } + } + launch { + configurationInteractor.configurationValues.collect { config -> + if (interestingChanges.applyNewConfig(config)) { + // Assumption: The context is always the same and with the same theme. + // If colors change they will be reflected as attributes in the theme. + qsImpl.value?.view?.let { inflate(it.context) } + } else { + qsImpl.value?.onConfigurationChanged(config) + qsImpl.value?.view?.dispatchConfigurationChanged(config) } - applyState(state) } } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModel.kt index e5e1e8445e94..8a900ece2750 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModel.kt @@ -16,7 +16,10 @@ package com.android.systemui.qs.ui.viewmodel +import androidx.lifecycle.LifecycleOwner import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.qs.FooterActionsController +import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel import com.android.systemui.qs.ui.adapter.QSSceneAdapter import com.android.systemui.scene.shared.model.Direction import com.android.systemui.scene.shared.model.SceneKey @@ -24,6 +27,7 @@ import com.android.systemui.scene.shared.model.SceneModel import com.android.systemui.scene.shared.model.UserAction import com.android.systemui.shade.ui.viewmodel.ShadeHeaderViewModel import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationsPlaceholderViewModel +import java.util.concurrent.atomic.AtomicBoolean import javax.inject.Inject import kotlinx.coroutines.flow.map @@ -35,6 +39,8 @@ constructor( val shadeHeaderViewModel: ShadeHeaderViewModel, val qsSceneAdapter: QSSceneAdapter, val notifications: NotificationsPlaceholderViewModel, + private val footerActionsViewModelFactory: FooterActionsViewModel.Factory, + private val footerActionsController: FooterActionsController, ) { val destinationScenes = qsSceneAdapter.isCustomizing.map { customizing -> @@ -47,4 +53,13 @@ constructor( ) } } + + private val footerActionsControllerInitialized = AtomicBoolean(false) + + fun getFooterActionsViewModel(lifecycleOwner: LifecycleOwner): FooterActionsViewModel { + if (footerActionsControllerInitialized.compareAndSet(false, true)) { + footerActionsController.init() + } + return footerActionsViewModelFactory.create(lifecycleOwner) + } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java index fd53423e7f22..cc53aabfcd25 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java +++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java @@ -169,7 +169,6 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis private final DisplayTracker mDisplayTracker; private Region mActiveNavBarRegion; - private SurfaceControl mNavigationBarSurface; private IOverviewProxy mOverviewProxy; private int mConnectionBackoffAttempts; @@ -488,7 +487,6 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis Log.e(TAG_OPS, "Failed to call onInitialize()", e); } dispatchNavButtonBounds(); - dispatchNavigationBarSurface(); // Force-update the systemui state flags updateSystemUiStateFlags(); @@ -679,28 +677,6 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis .commitUpdate(mContext.getDisplayId()); } - /** - * Called when the navigation bar surface is created or changed - */ - public void onNavigationBarSurfaceChanged(SurfaceControl navbarSurface) { - mNavigationBarSurface = navbarSurface; - dispatchNavigationBarSurface(); - } - - private void dispatchNavigationBarSurface() { - try { - if (mOverviewProxy != null) { - // Catch all for cases where the surface is no longer valid - if (mNavigationBarSurface != null && !mNavigationBarSurface.isValid()) { - mNavigationBarSurface = null; - } - mOverviewProxy.onNavigationBarSurface(mNavigationBarSurface); - } - } catch (RemoteException e) { - Log.e(TAG_OPS, "Failed to notify back action", e); - } - } - private void updateEnabledAndBinding() { updateEnabledState(); startConnectionToCurrentUser(); @@ -1075,7 +1051,6 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis pw.print(" mInputFocusTransferStartY="); pw.println(mInputFocusTransferStartY); pw.print(" mInputFocusTransferStartMillis="); pw.println(mInputFocusTransferStartMillis); pw.print(" mActiveNavBarRegion="); pw.println(mActiveNavBarRegion); - pw.print(" mNavigationBarSurface="); pw.println(mNavigationBarSurface); pw.print(" mNavBarMode="); pw.println(mNavBarMode); mSysUiState.dump(pw, args); } diff --git a/packages/SystemUI/src/com/android/systemui/shade/GlanceableHubContainerController.kt b/packages/SystemUI/src/com/android/systemui/shade/GlanceableHubContainerController.kt index 782d6519468c..44cb0d6ff2ba 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/GlanceableHubContainerController.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/GlanceableHubContainerController.kt @@ -55,7 +55,22 @@ constructor( * The width of the area in which a right edge swipe can open the hub, in pixels. Read from * resources when [initView] is called. */ - private var edgeSwipeRegionWidth: Int = 0 + // TODO(b/320786721): support RTL layouts + private var rightEdgeSwipeRegionWidth: Int = 0 + + /** + * The height of the area in which a top edge swipe while the hub is open will not intercept + * touches, in pixels. This allows the top edge swipe to instead open the notification shade. + * Read from resources when [initView] is called. + */ + private var topEdgeSwipeRegionWidth: Int = 0 + + /** + * The height of the area in which a bottom edge swipe while the hub is open will not intercept + * touches, in pixels. This allows the bottom edge swipe to instead open the bouncer. Read from + * resources when [initView] is called. + */ + private var bottomEdgeSwipeRegionWidth: Int = 0 /** * True if we are currently tracking a gesture for opening the hub that started in the edge @@ -63,6 +78,9 @@ constructor( */ private var isTrackingOpenGesture = false + /** True if we are currently tracking a touch on the hub while it's open. */ + private var isTrackingHubTouch = false + /** * True if the hub UI is fully open, meaning it should receive touch input. * @@ -113,8 +131,18 @@ constructor( communalContainerView = containerView - edgeSwipeRegionWidth = - communalContainerView.resources.getDimensionPixelSize(R.dimen.communal_grid_gutter_size) + rightEdgeSwipeRegionWidth = + communalContainerView.resources.getDimensionPixelSize( + R.dimen.communal_right_edge_swipe_region_width + ) + topEdgeSwipeRegionWidth = + communalContainerView.resources.getDimensionPixelSize( + R.dimen.communal_top_edge_swipe_region_height + ) + bottomEdgeSwipeRegionWidth = + communalContainerView.resources.getDimensionPixelSize( + R.dimen.communal_bottom_edge_swipe_region_height + ) collectFlow( communalContainerView, @@ -157,17 +185,38 @@ constructor( // fully showing state val hubOccluded = anyBouncerShowing || shadeShowing - // If the hub is fully visible, send all touch events to it. - val communalVisible = hubShowing && !hubOccluded - if (communalVisible) { + // If the hub is fully visible, send all touch events to it, other than top and bottom edge + // swipes. + if (hubShowing && isDown) { + val y = ev.rawY + val topSwipe: Boolean = y <= topEdgeSwipeRegionWidth + val bottomSwipe = y >= communalContainerView.height - bottomEdgeSwipeRegionWidth + + if (topSwipe || bottomSwipe) { + // Don't intercept touches at the top/bottom edge so that swipes can open the + // notification shade and bouncer. + return false + } + + if (!hubOccluded) { + isTrackingHubTouch = true + dispatchTouchEvent(ev) + // Return true regardless of dispatch result as some touches at the start of a + // gesture may return false from dispatchTouchEvent. + return true + } + } else if (isTrackingHubTouch) { + if (isUp || isCancel) { + isTrackingHubTouch = false + } dispatchTouchEvent(ev) // Return true regardless of dispatch result as some touches at the start of a gesture // may return false from dispatchTouchEvent. return true } - if (edgeSwipeRegionWidth == 0) { - // If the edge region width has not been read yet or whatever reason, don't bother + if (rightEdgeSwipeRegionWidth == 0) { + // If the edge region width has not been read yet for whatever reason, don't bother // intercepting touches to open the hub. return false } @@ -175,7 +224,7 @@ constructor( if (!isTrackingOpenGesture && isDown) { val x = ev.rawX val inOpeningSwipeRegion: Boolean = - x >= communalContainerView.width - edgeSwipeRegionWidth + x >= communalContainerView.width - rightEdgeSwipeRegionWidth if (inOpeningSwipeRegion && !hubOccluded) { isTrackingOpenGesture = true dispatchTouchEvent(ev) diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java index 60feb82bf4aa..00534743588c 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java @@ -50,6 +50,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.Dumpable; import com.android.systemui.biometrics.AuthController; import com.android.systemui.colorextraction.SysuiColorExtractor; +import com.android.systemui.communal.domain.interactor.CommunalInteractor; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; @@ -118,6 +119,7 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW private final Lazy<SelectedUserInteractor> mUserInteractor; private final Lazy<ShadeInteractor> mShadeInteractorLazy; private final SceneContainerFlags mSceneContainerFlags; + private final Lazy<CommunalInteractor> mCommunalInteractor; private ViewGroup mWindowRootView; private LayoutParams mLp; private boolean mHasTopUi; @@ -165,7 +167,8 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW ShadeWindowLogger logger, Lazy<SelectedUserInteractor> userInteractor, UserTracker userTracker, - SceneContainerFlags sceneContainerFlags) { + SceneContainerFlags sceneContainerFlags, + Lazy<CommunalInteractor> communalInteractor) { mContext = context; mWindowRootViewComponentFactory = windowRootViewComponentFactory; mWindowManager = windowManager; @@ -184,6 +187,7 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW mAuthController = authController; mUserInteractor = userInteractor; mSceneContainerFlags = sceneContainerFlags; + mCommunalInteractor = communalInteractor; mLastKeyguardRotationAllowed = mKeyguardStateController.isKeyguardScreenRotationAllowed(); mLockScreenDisplayTimeout = context.getResources() .getInteger(R.integer.config_lockScreenDisplayTimeout); @@ -325,6 +329,11 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW mShadeInteractorLazy.get().isQsExpanded(), this::onQsExpansionChanged ); + collectFlow( + mWindowRootView, + mCommunalInteractor.get().isCommunalShowing(), + this::onCommunalShowingChanged + ); } @Override @@ -501,14 +510,21 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW } private void applyUserActivityTimeout(NotificationShadeWindowState state) { - if (state.isKeyguardShowingAndNotOccluded() + final Boolean communalShowing = state.isCommunalShowingAndNotOccluded(); + final Boolean keyguardShowing = state.isKeyguardShowingAndNotOccluded(); + long timeout = -1; + if ((communalShowing || keyguardShowing) && state.statusBarState == StatusBarState.KEYGUARD && !state.qsExpanded) { - mLpChanged.userActivityTimeout = state.bouncerShowing - ? KeyguardViewMediator.AWAKE_INTERVAL_BOUNCER_MS : mLockScreenDisplayTimeout; - } else { - mLpChanged.userActivityTimeout = -1; + if (state.bouncerShowing) { + timeout = KeyguardViewMediator.AWAKE_INTERVAL_BOUNCER_MS; + } else if (communalShowing) { + timeout = CommunalInteractor.AWAKE_INTERVAL_MS; + } else if (keyguardShowing) { + timeout = mLockScreenDisplayTimeout; + } } + mLpChanged.userActivityTimeout = timeout; } private void applyInputFeatures(NotificationShadeWindowState state) { @@ -607,7 +623,8 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW state.forcePluginOpen, state.dozing, state.scrimsVisibility, - state.backgroundBlurRadius + state.backgroundBlurRadius, + state.communalShowing ); } @@ -731,6 +748,12 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW apply(mCurrentState); } + @VisibleForTesting + void onCommunalShowingChanged(Boolean showing) { + mCurrentState.communalShowing = showing; + apply(mCurrentState); + } + @Override public void setForceUserActivity(boolean forceUserActivity) { mCurrentState.forceUserActivity = forceUserActivity; diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowState.kt b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowState.kt index 0b20170834d8..f9c9d83e03aa 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowState.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowState.kt @@ -58,12 +58,17 @@ class NotificationShadeWindowState( @JvmField var dreaming: Boolean = false, @JvmField var scrimsVisibility: Int = 0, @JvmField var backgroundBlurRadius: Int = 0, + @JvmField var communalShowing: Boolean = false, ) { fun isKeyguardShowingAndNotOccluded(): Boolean { return keyguardShowing && !keyguardOccluded } + fun isCommunalShowingAndNotOccluded(): Boolean { + return communalShowing && !keyguardOccluded + } + /** List of [String] to be used as a [Row] with [DumpsysTableLogger]. */ val asStringList: List<String> by lazy { listOf( @@ -93,7 +98,8 @@ class NotificationShadeWindowState( forcePluginOpen.toString(), dozing.toString(), scrimsVisibility.toString(), - backgroundBlurRadius.toString() + backgroundBlurRadius.toString(), + communalShowing.toString(), ) } @@ -134,6 +140,7 @@ class NotificationShadeWindowState( dozing: Boolean, scrimsVisibility: Int, backgroundBlurRadius: Int, + communalShowing: Boolean, ) { buffer.advance().apply { this.keyguardShowing = keyguardShowing @@ -165,6 +172,7 @@ class NotificationShadeWindowState( this.dozing = dozing this.scrimsVisibility = scrimsVisibility this.backgroundBlurRadius = backgroundBlurRadius + this.communalShowing = communalShowing } } @@ -209,7 +217,8 @@ class NotificationShadeWindowState( "forcePluginOpen", "dozing", "scrimsVisibility", - "backgroundBlurRadius" + "backgroundBlurRadius", + "communalShowing" ) } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutListSearch.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutListSearch.java index 909cff37b67d..e5982428fe14 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutListSearch.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutListSearch.java @@ -542,7 +542,19 @@ public final class KeyboardShortcutListSearch { new ShortcutKeyGroupMultiMappingInfo( context.getString(R.string.group_system_access_google_assistant), Arrays.asList( - Pair.create(KeyEvent.KEYCODE_A, KeyEvent.META_META_ON))) + Pair.create(KeyEvent.KEYCODE_A, KeyEvent.META_META_ON))), + /* Lock screen: Meta + L */ + new ShortcutKeyGroupMultiMappingInfo( + context.getString(R.string.group_system_lock_screen), + Arrays.asList( + Pair.create(KeyEvent.KEYCODE_L, KeyEvent.META_META_ON))), + /* Pull up Notes app for quick memo: Meta + Ctrl + N */ + new ShortcutKeyGroupMultiMappingInfo( + context.getString(R.string.group_system_quick_memo), + Arrays.asList( + Pair.create( + KeyEvent.KEYCODE_N, + KeyEvent.META_META_ON | KeyEvent.META_CTRL_ON))) ); for (ShortcutKeyGroupMultiMappingInfo info : infoList) { systemGroup.addItem(info.getShortcutMultiMappingInfo()); @@ -584,11 +596,17 @@ public final class KeyboardShortcutListSearch { new ArrayList<>()); // System multitasking shortcuts: + // Enter Split screen with current app to RHS: Meta + Ctrl + Right arrow + // Enter Split screen with current app to LHS: Meta + Ctrl + Left arrow // Switch from Split screen to full screen: Meta + Ctrl + Up arrow String[] shortcutLabels = { + context.getString(R.string.system_multitasking_rhs), + context.getString(R.string.system_multitasking_lhs), context.getString(R.string.system_multitasking_full_screen), }; int[] keyCodes = { + KeyEvent.KEYCODE_DPAD_RIGHT, + KeyEvent.KEYCODE_DPAD_LEFT, KeyEvent.KEYCODE_DPAD_UP, }; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt index 46806e66cb8c..54b6ad71e734 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt @@ -790,7 +790,7 @@ private fun <R> HeadsUpManager.modifyHuns(block: (HunMutator) -> R): R { /** Mutates the HeadsUp state of notifications. */ private interface HunMutator { - fun updateNotification(key: String, alert: Boolean) + fun updateNotification(key: String, shouldHeadsUpAgain: Boolean) fun removeNotification(key: String, releaseImmediately: Boolean) } @@ -801,8 +801,8 @@ private interface HunMutator { private class HunMutatorImpl(private val headsUpManager: HeadsUpManager) : HunMutator { private val deferred = mutableListOf<Pair<String, Boolean>>() - override fun updateNotification(key: String, alert: Boolean) { - headsUpManager.updateNotification(key, alert) + override fun updateNotification(key: String, shouldHeadsUpAgain: Boolean) { + headsUpManager.updateNotification(key, shouldHeadsUpAgain) } override fun removeNotification(key: String, releaseImmediately: Boolean) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt index 226a9577c820..bd659d294223 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt @@ -23,6 +23,7 @@ import com.android.systemui.statusbar.notification.collection.PipelineDumper import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner import com.android.systemui.statusbar.notification.collection.provider.SectionStyleProvider +import com.android.systemui.statusbar.notification.shared.NotificationsLiveDataStoreRefactor import javax.inject.Inject /** @@ -61,6 +62,7 @@ class NotifCoordinatorsImpl @Inject constructor( sensitiveContentCoordinator: SensitiveContentCoordinator, dismissibilityCoordinator: DismissibilityCoordinator, dreamCoordinator: DreamCoordinator, + statsLoggerCoordinator: NotificationStatsLoggerCoordinator, ) : NotifCoordinators { private val mCoreCoordinators: MutableList<CoreCoordinator> = ArrayList() @@ -104,6 +106,10 @@ class NotifCoordinatorsImpl @Inject constructor( mCoordinators.add(dreamCoordinator) } + if (NotificationsLiveDataStoreRefactor.isEnabled) { + mCoordinators.add(statsLoggerCoordinator) + } + // Manually add Ordered Sections mOrderedSections.add(headsUpCoordinator.sectioner) // HeadsUp mOrderedSections.add(colorizedFgsCoordinator.sectioner) // ForegroundService diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotificationStatsLoggerCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotificationStatsLoggerCoordinator.kt new file mode 100644 index 000000000000..6e81d9322be5 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotificationStatsLoggerCoordinator.kt @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.notification.collection.coordinator + +import com.android.systemui.statusbar.notification.collection.NotifPipeline +import com.android.systemui.statusbar.notification.collection.NotificationEntry +import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope +import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener +import com.android.systemui.statusbar.notification.shared.NotificationsLiveDataStoreRefactor +import com.android.systemui.statusbar.notification.stack.ui.view.NotificationStatsLogger +import java.util.Optional +import javax.inject.Inject + +@CoordinatorScope +class NotificationStatsLoggerCoordinator +@Inject +constructor(private val loggerOptional: Optional<NotificationStatsLogger>) : Coordinator { + + private val collectionListener = + object : NotifCollectionListener { + override fun onEntryUpdated(entry: NotificationEntry) { + super.onEntryUpdated(entry) + loggerOptional.ifPresent { it.onNotificationUpdated(entry.key) } + } + + override fun onEntryRemoved(entry: NotificationEntry, reason: Int) { + super.onEntryRemoved(entry, reason) + loggerOptional.ifPresent { it.onNotificationRemoved(entry.key) } + } + } + override fun attach(pipeline: NotifPipeline) { + if (NotificationsLiveDataStoreRefactor.isUnexpectedlyInLegacyMode()) { + return + } + pipeline.addCollectionListener(collectionListener) + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinator.kt index 380cdadd1361..ae4ba27775b8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinator.kt @@ -18,6 +18,7 @@ package com.android.systemui.statusbar.notification.collection.coordinator import android.os.UserHandle import com.android.keyguard.KeyguardUpdateMonitor +import com.android.systemui.Flags.screenshareNotificationHiding import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.statusbar.NotificationLockscreenUserManager import com.android.systemui.statusbar.StatusBarState @@ -30,6 +31,7 @@ import com.android.systemui.statusbar.notification.collection.coordinator.dagger import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Invalidator import com.android.systemui.statusbar.policy.KeyguardStateController +import com.android.systemui.statusbar.policy.SensitiveNotificationProtectionController import com.android.systemui.user.domain.interactor.SelectedUserInteractor import dagger.Binds import dagger.Module @@ -55,6 +57,8 @@ class SensitiveContentCoordinatorImpl @Inject constructor( private val statusBarStateController: StatusBarStateController, private val keyguardStateController: KeyguardStateController, private val selectedUserInteractor: SelectedUserInteractor, + private val sensitiveNotificationProtectionController: + SensitiveNotificationProtectionController, ) : Invalidator("SensitiveContentInvalidator"), SensitiveContentCoordinator, DynamicPrivacyController.Listener, @@ -82,10 +86,13 @@ class SensitiveContentCoordinatorImpl @Inject constructor( return } + val isSensitiveContentProtectionActive = screenshareNotificationHiding() && + sensitiveNotificationProtectionController.isSensitiveStateActive val currentUserId = lockscreenUserManager.currentUserId val devicePublic = lockscreenUserManager.isLockscreenPublicMode(currentUserId) - val deviceSensitive = devicePublic && - !lockscreenUserManager.userAllowsPrivateNotificationsInPublic(currentUserId) + val deviceSensitive = (devicePublic && + !lockscreenUserManager.userAllowsPrivateNotificationsInPublic(currentUserId)) || + isSensitiveContentProtectionActive val dynamicallyUnlocked = dynamicPrivacyController.isDynamicallyUnlocked for (entry in extractAllRepresentativeEntries(entries).filter { it.rowExists() }) { val notifUserId = entry.sbn.user.identifier @@ -105,9 +112,13 @@ class SensitiveContentCoordinatorImpl @Inject constructor( else -> lockscreenUserManager.needsSeparateWorkChallenge(notifUserId) } } + + val shouldProtectNotification = screenshareNotificationHiding() && + sensitiveNotificationProtectionController.shouldProtectNotification(entry) + val needsRedaction = lockscreenUserManager.needsRedaction(entry) val isSensitive = userPublic && needsRedaction - entry.setSensitive(isSensitive, deviceSensitive) + entry.setSensitive(isSensitive || shouldProtectNotification, deviceSensitive) } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconContainerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconContainerViewBinder.kt index ae772880f148..f375ebce2de3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconContainerViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconContainerViewBinder.kt @@ -142,7 +142,7 @@ object NotificationIconContainerViewBinder { /** Binds to [NotificationIconContainer.setAnimationsEnabled] */ private suspend fun Flow<Boolean>.bindAnimationsEnabled(view: NotificationIconContainer) { - collect(view::setAnimationsEnabled) + collectTracingEach("NIC#bindAnimationsEnabled", view::setAnimationsEnabled) } private suspend fun NotificationIconContainerStatusBarViewModel.bindIsolatedIcon( @@ -151,12 +151,12 @@ object NotificationIconContainerViewBinder { ) { coroutineScope { launch { - isolatedIconLocation.collect { location -> + isolatedIconLocation.collectTracingEach("NIC#isolatedIconLocation") { location -> view.setIsolatedIconLocation(location, true) } } launch { - isolatedIcon.collect { iconInfo -> + isolatedIcon.collectTracingEach("NIC#showIconIsolated") { iconInfo -> val iconView = iconInfo.value?.let { viewStore.iconView(it.notifKey) } if (iconInfo.isAnimating) { view.showIconIsolatedAnimated(iconView, iconInfo::stopAnimating) @@ -187,7 +187,7 @@ object NotificationIconContainerViewBinder { configuration.getDimensionPixelSize(RInternal.dimen.status_bar_icon_size_sp) val iconHorizontalPaddingFlow: Flow<Int> = configuration.getDimensionPixelSize(R.dimen.status_bar_icon_horizontal_margin) - val layoutParams: Flow<FrameLayout.LayoutParams> = + val layoutParams: StateFlow<FrameLayout.LayoutParams> = combine(iconSizeFlow, iconHorizontalPaddingFlow, systemBarUtilsState.statusBarHeight) { iconSize, iconHPadding, @@ -206,7 +206,7 @@ object NotificationIconContainerViewBinder { private suspend fun Flow<NotificationIconsViewData>.bindIcons( view: NotificationIconContainer, - layoutParams: Flow<FrameLayout.LayoutParams>, + layoutParams: StateFlow<FrameLayout.LayoutParams>, notifyBindingFailures: (Collection<String>) -> Unit, viewStore: IconViewStore, bindIcon: suspend (iconKey: String, view: StatusBarIconView) -> Unit, @@ -214,7 +214,7 @@ object NotificationIconContainerViewBinder { val failedBindings = mutableSetOf<String>() val boundViewsByNotifKey = ArrayMap<String, Pair<StatusBarIconView, Job>>() var prevIcons = NotificationIconsViewData() - collectTracingEach("NotifIconContainer#bindIcons") { iconsData: NotificationIconsViewData -> + collectTracingEach("NIC#bindIcons") { iconsData: NotificationIconsViewData -> val iconsDiff = NotificationIconsViewData.computeDifference(iconsData, prevIcons) prevIcons = iconsData @@ -259,13 +259,19 @@ object NotificationIconContainerViewBinder { // added again. removeTransientView(sbiv) } - view.addView(sbiv) + view.addView(sbiv, layoutParams.value) boundViewsByNotifKey.remove(notifKey)?.second?.cancel() boundViewsByNotifKey[notifKey] = Pair( sbiv, launch { - launch { layoutParams.collect { sbiv.layoutParams = it } } + launch { + layoutParams.collectTracingEach("SBIV#bindLayoutParams") { + if (it != sbiv.layoutParams) { + sbiv.layoutParams = it + } + } + } bindIcon(notifKey, sbiv) }, ) @@ -369,6 +375,7 @@ private val View.viewBounds: Rect ) } -private suspend fun <T> Flow<T>.collectTracingEach(tag: String, collector: (T) -> Unit) { - collect { traceSection(tag) { collector(it) } } -} +private suspend inline fun <T> Flow<T>.collectTracingEach( + tag: String, + crossinline collector: (T) -> Unit, +) = collect { traceSection(tag) { collector(it) } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/StatusBarIconViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/StatusBarIconViewBinder.kt index 03316548e979..bfeaced72162 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/StatusBarIconViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/StatusBarIconViewBinder.kt @@ -18,6 +18,7 @@ package com.android.systemui.statusbar.notification.icon.ui.viewbinder import android.graphics.Rect import android.view.View +import com.android.app.tracing.traceSection import com.android.internal.util.ContrastColorUtil import com.android.systemui.res.R import com.android.systemui.statusbar.StatusBarIconView @@ -33,18 +34,18 @@ object StatusBarIconViewBinder { // view-model (which, at the time of this writing, does not yet exist). suspend fun bindColor(view: StatusBarIconView, color: Flow<Int>) { - color.collect { color -> + color.collectTracingEach("SBIV#bindColor") { color -> view.staticDrawableColor = color view.setDecorColor(color) } } suspend fun bindTintAlpha(view: StatusBarIconView, tintAlpha: Flow<Float>) { - tintAlpha.collect { amt -> view.setTintAlpha(amt) } + tintAlpha.collectTracingEach("SBIV#bindTintAlpha") { amt -> view.setTintAlpha(amt) } } suspend fun bindAnimationsEnabled(view: StatusBarIconView, allowAnimation: Flow<Boolean>) { - allowAnimation.collect(view::setAllowAnimation) + allowAnimation.collectTracingEach("SBIV#bindAnimationsEnabled", view::setAllowAnimation) } suspend fun bindIconColors( @@ -52,7 +53,7 @@ object StatusBarIconViewBinder { iconColors: Flow<NotificationIconColors>, contrastColorUtil: ContrastColorUtil, ) { - iconColors.collect { colors -> + iconColors.collectTracingEach("SBIV#bindIconColors") { colors -> val isPreL = java.lang.Boolean.TRUE == view.getTag(R.id.icon_is_pre_L) val isColorized = !isPreL || NotificationUtils.isGrayscale(view, contrastColorUtil) view.staticDrawableColor = @@ -73,3 +74,8 @@ private val View.viewBounds: Rect /* bottom = */ top + height, ) } + +private suspend inline fun <T> Flow<T>.collectTracingEach( + tag: String, + crossinline collector: (T) -> Unit, +) = collect { traceSection(tag) { collector(it) } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowModule.java index 3a59978d415c..46ddba4d4d8d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowModule.java @@ -65,9 +65,7 @@ public abstract class NotificationRowModule { CallLayoutSetDataAsyncFactory callLayoutSetDataAsyncFactory ) { final Set<NotifRemoteViewsFactory> replacementFactories = new HashSet<>(); - if (featureFlags.isEnabled(Flags.PRECOMPUTED_TEXT)) { - replacementFactories.add(precomputedTextViewFactory); - } + replacementFactories.add(precomputedTextViewFactory); if (featureFlags.isEnabled(Flags.BIGPICTURE_NOTIFICATION_LAZY_LOADING)) { replacementFactories.add(bigPictureLayoutInflaterFactory); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/shared/NotificationAvalancheSuppression.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/shared/NotificationAvalancheSuppression.kt new file mode 100644 index 000000000000..a21dd9bb9579 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/shared/NotificationAvalancheSuppression.kt @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.notification.shared + +import com.android.systemui.Flags +import com.android.systemui.flags.FlagToken +import com.android.systemui.flags.RefactorFlagUtils + +/** Helper for reading or using the notification avalanche suppression flag state. */ +@Suppress("NOTHING_TO_INLINE") +object NotificationAvalancheSuppression { + /** The aconfig flag name */ + const val FLAG_NAME = Flags.FLAG_NOTIFICATION_AVALANCHE_SUPPRESSION + + /** A token used for dependency declaration */ + val token: FlagToken + get() = FlagToken(FLAG_NAME, isEnabled) + + /** Is the refactor enabled */ + @JvmStatic + inline val isEnabled + get() = Flags.notificationAvalancheSuppression() + + /** + * Called to ensure code is only run when the flag is enabled. This protects users from the + * unintended behaviors caused by accidentally running new logic, while also crashing on an eng + * build to ensure that the refactor author catches issues in testing. + */ + @JvmStatic + inline fun isUnexpectedlyInLegacyMode() = + RefactorFlagUtils.isUnexpectedlyInLegacyMode(isEnabled, FLAG_NAME) + + /** + * Called to ensure code is only run when the flag is disabled. This will throw an exception if + * the flag is enabled to ensure that the refactor author catches issues in testing. + */ + @JvmStatic + inline fun assertInLegacyMode() = RefactorFlagUtils.assertInLegacyMode(isEnabled, FLAG_NAME) +}
\ No newline at end of file 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 6a66bb74f16d..1143481863f5 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 @@ -22,6 +22,7 @@ import static android.service.notification.NotificationStats.DISMISS_SENTIMENT_N import static com.android.app.animation.Interpolators.STANDARD; import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_SCROLL_FLING; import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME; +import static com.android.systemui.Flags.screenshareNotificationHiding; import static com.android.systemui.statusbar.StatusBarState.KEYGUARD; import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.OnEmptySpaceClickListener; import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.OnOverscrollTopChangedListener; @@ -135,6 +136,7 @@ import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener; import com.android.systemui.statusbar.policy.HeadsUpManager; import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener; +import com.android.systemui.statusbar.policy.SensitiveNotificationProtectionController; import com.android.systemui.statusbar.policy.SplitShadeStateController; import com.android.systemui.statusbar.policy.ZenModeController; import com.android.systemui.tuner.TunerService; @@ -218,6 +220,8 @@ public class NotificationStackScrollLayoutController implements Dumpable { private final SecureSettings mSecureSettings; private final NotificationDismissibilityProvider mDismissibilityProvider; private final ActivityStarter mActivityStarter; + private final SensitiveNotificationProtectionController + mSensitiveNotificationProtectionController; private View mLongPressedView; @@ -295,6 +299,15 @@ public class NotificationStackScrollLayoutController implements Dumpable { } }; + private final Runnable mSensitiveStateChangedListener = new Runnable() { + @Override + public void run() { + // Animate false to protect against screen recording capturing content + // during the animation + updateSensitivenessWithAnimation(false); + } + }; + private final DynamicPrivacyController.Listener mDynamicPrivacyControllerListener = () -> { if (mView.isExpanded()) { // The bottom might change because we're using the final actual height of the view @@ -342,6 +355,12 @@ public class NotificationStackScrollLayoutController implements Dumpable { private float mMaxAlphaForExpansion = 1.0f; private float mMaxAlphaForUnhide = 1.0f; + /** + * Maximum alpha when to and from or sitting idle on the glanceable hub. Will be 1.0f when the + * hub is not visible or transitioning. + */ + private float mMaxAlphaForGlanceableHub = 1.0f; + private final NotificationListViewBinder mViewBinder; private void updateResources() { @@ -399,7 +418,20 @@ public class NotificationStackScrollLayoutController implements Dumpable { } private void updateSensitivenessWithAnimation(boolean animate) { - mView.updateSensitiveness(animate, mLockscreenUserManager.isAnyProfilePublicMode()); + Trace.beginSection("NSSLC.updateSensitivenessWithAnimation"); + if (screenshareNotificationHiding()) { + boolean isAnyProfilePublic = mLockscreenUserManager.isAnyProfilePublicMode(); + boolean isSensitiveContentProtectionActive = + mSensitiveNotificationProtectionController.isSensitiveStateActive(); + boolean isSensitive = isAnyProfilePublic || isSensitiveContentProtectionActive; + + // Only animate if in a non-sensitive state (not screen sharing) + boolean shouldAnimate = animate && !isSensitiveContentProtectionActive; + mView.updateSensitiveness(shouldAnimate, isSensitive); + } else { + mView.updateSensitiveness(animate, mLockscreenUserManager.isAnyProfilePublicMode()); + } + Trace.endSection(); } /** @@ -708,7 +740,8 @@ public class NotificationStackScrollLayoutController implements Dumpable { SecureSettings secureSettings, NotificationDismissibilityProvider dismissibilityProvider, ActivityStarter activityStarter, - SplitShadeStateController splitShadeStateController) { + SplitShadeStateController splitShadeStateController, + SensitiveNotificationProtectionController sensitiveNotificationProtectionController) { mView = view; mKeyguardTransitionRepo = keyguardTransitionRepo; mViewBinder = viewBinder; @@ -756,6 +789,7 @@ public class NotificationStackScrollLayoutController implements Dumpable { mSecureSettings = secureSettings; mDismissibilityProvider = dismissibilityProvider; mActivityStarter = activityStarter; + mSensitiveNotificationProtectionController = sensitiveNotificationProtectionController; mView.passSplitShadeStateController(splitShadeStateController); mDumpManager.registerDumpable(this); updateResources(); @@ -860,6 +894,11 @@ public class NotificationStackScrollLayoutController implements Dumpable { mDeviceProvisionedController.addCallback(mDeviceProvisionedListener); mDeviceProvisionedListener.onDeviceProvisionedChanged(); + if (screenshareNotificationHiding()) { + mSensitiveNotificationProtectionController + .registerSensitiveStateListener(mSensitiveStateChangedListener); + } + if (mView.isAttachedToWindow()) { mOnAttachStateChangeListener.onViewAttachedToWindow(mView); } @@ -1252,9 +1291,19 @@ public class NotificationStackScrollLayoutController implements Dumpable { updateAlpha(); } + /** + * Sets the max alpha value for notifications when idle on the glanceable hub or when + * transitioning to/from the glanceable hub. + */ + public void setMaxAlphaForGlanceableHub(float alpha) { + mMaxAlphaForGlanceableHub = alpha; + updateAlpha(); + } + private void updateAlpha() { if (mView != null) { - mView.setAlpha(Math.min(mMaxAlphaForExpansion, mMaxAlphaForUnhide)); + mView.setAlpha(Math.min(mMaxAlphaForExpansion, + Math.min(mMaxAlphaForUnhide, mMaxAlphaForGlanceableHub))); } } @@ -1746,6 +1795,7 @@ public class NotificationStackScrollLayoutController implements Dumpable { public void dump(@NonNull PrintWriter pw, @NonNull String[] args) { pw.println("mMaxAlphaForExpansion=" + mMaxAlphaForExpansion); pw.println("mMaxAlphaForUnhide=" + mMaxAlphaForUnhide); + pw.println("mMaxAlphaForGlanceableHub=" + mMaxAlphaForGlanceableHub); } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/view/NotificationStatsLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/view/NotificationStatsLogger.kt index 54186165c54a..365c02f74bfe 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/view/NotificationStatsLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/view/NotificationStatsLogger.kt @@ -29,9 +29,7 @@ interface NotificationStatsLogger : NotificationRowStatsLogger { activeNotifications: List<ActiveNotificationModel>, ) fun onLockscreenOrShadeNotInteractive(activeNotifications: List<ActiveNotificationModel>) - fun onNotificationRemoved(key: String) - fun onNotificationUpdated(key: String) - fun onNotificationListUpdated( + fun onNotificationLocationsChanged( locationsProvider: Callable<Map<String, Int>>, notificationRanks: Map<String, Int>, ) @@ -41,4 +39,6 @@ interface NotificationStatsLogger : NotificationRowStatsLogger { location: Int, isUserAction: Boolean ) + fun onNotificationRemoved(key: String) + fun onNotificationUpdated(key: String) } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/view/NotificationStatsLoggerImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/view/NotificationStatsLoggerImpl.kt index 0cb00bc8d01d..4897b4275f75 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/view/NotificationStatsLoggerImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/view/NotificationStatsLoggerImpl.kt @@ -53,10 +53,11 @@ constructor( private val expansionStates: MutableMap<String, ExpansionState> = ConcurrentHashMap<String, ExpansionState>() - private val lastReportedExpansionValues: MutableMap<String, Boolean> = + @VisibleForTesting + val lastReportedExpansionValues: MutableMap<String, Boolean> = ConcurrentHashMap<String, Boolean>() - override fun onNotificationListUpdated( + override fun onNotificationLocationsChanged( locationsProvider: Callable<Map<String, Int>>, notificationRanks: Map<String, Int>, ) { @@ -152,14 +153,12 @@ constructor( ) } - // TODO(b/308623704) wire this in with NotifPipeline updates override fun onNotificationRemoved(key: String) { // No need to track expansion states for Notifications that are removed. expansionStates.remove(key) lastReportedExpansionValues.remove(key) } - // TODO(b/308623704) wire this in with NotifPipeline updates override fun onNotificationUpdated(key: String) { // When the Notification is updated, we should consider it as not yet logged. lastReportedExpansionValues.remove(key) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationStatsLoggerBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationStatsLoggerBinder.kt index a05ad6e45991..a87c85fcaaea 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationStatsLoggerBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationStatsLoggerBinder.kt @@ -41,6 +41,8 @@ object NotificationStatsLoggerBinder { logger: NotificationStatsLogger, viewModel: NotificationLoggerViewModel, ) { + // Updates the logger about whether the Notification panel, and the individual Notifications + // are visible to the user. viewModel.isLockscreenOrShadeInteractive .sample( combine(viewModel.isOnLockScreen, viewModel.activeNotifications, ::Pair), @@ -52,14 +54,14 @@ object NotificationStatsLoggerBinder { isOnLockScreen = isOnLockScreen, activeNotifications = notifications, ) - view.onNotificationsUpdated - // Delay the updates with [NOTIFICATION_UPDATES_PERIOD_MS]. If the original + view.onNotificationLocationsUpdated + // Delay the updates with [NOTIFICATION_UPDATE_PERIOD_MS]. If the original // flow emits more than once during this period, only the latest value is // emitted, meaning that we won't log the intermediate Notification states. .throttle(NOTIFICATION_UPDATE_PERIOD_MS) .sample(viewModel.activeNotificationRanks, ::Pair) - .collect { (locationsProvider, notificationRanks) -> - logger.onNotificationListUpdated(locationsProvider, notificationRanks) + .collect { (locationsProvider, ranks) -> + logger.onNotificationLocationsChanged(locationsProvider, ranks) } } else { logger.onLockscreenOrShadeNotInteractive( @@ -70,7 +72,7 @@ object NotificationStatsLoggerBinder { } } -private val NotificationStackScrollLayout.onNotificationsUpdated +private val NotificationStackScrollLayout.onNotificationLocationsUpdated get() = ConflatedCallbackFlow.conflatedCallbackFlow { val callback = diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt index 12927b87630e..f842e304ffdf 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt @@ -18,7 +18,6 @@ package com.android.systemui.statusbar.notification.stack.ui.viewbinder import android.animation.Animator import android.animation.AnimatorListenerAdapter -import android.animation.ValueAnimator import androidx.lifecycle.Lifecycle import androidx.lifecycle.repeatOnLifecycle import com.android.systemui.dagger.qualifiers.Main @@ -125,7 +124,14 @@ object SharedNotificationContainerBinder { launch { viewModel.translationY.collect { controller.setTranslationY(it) } } - launch { viewModel.alpha.collect { controller.setMaxAlphaForExpansion(it) } } + launch { + viewModel.expansionAlpha.collect { controller.setMaxAlphaForExpansion(it) } + } + launch { + viewModel.glanceableHubAlpha.collect { + controller.setMaxAlphaForGlanceableHub(it) + } + } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt index a48fb45861d2..99cd89b84c14 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt @@ -20,6 +20,7 @@ package com.android.systemui.statusbar.notification.stack.ui.viewmodel import com.android.systemui.common.shared.model.NotificationContainerBounds +import com.android.systemui.communal.domain.interactor.CommunalInteractor import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor @@ -27,6 +28,8 @@ import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.shared.model.StatusBarState.SHADE_LOCKED import com.android.systemui.keyguard.shared.model.TransitionState.RUNNING import com.android.systemui.keyguard.shared.model.TransitionState.STARTED +import com.android.systemui.keyguard.ui.viewmodel.GlanceableHubToLockscreenTransitionViewModel +import com.android.systemui.keyguard.ui.viewmodel.LockscreenToGlanceableHubTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.LockscreenToOccludedTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.OccludedToLockscreenTransitionViewModel import com.android.systemui.shade.domain.interactor.ShadeInteractor @@ -61,8 +64,11 @@ constructor( private val keyguardInteractor: KeyguardInteractor, keyguardTransitionInteractor: KeyguardTransitionInteractor, private val shadeInteractor: ShadeInteractor, + communalInteractor: CommunalInteractor, occludedToLockscreenTransitionViewModel: OccludedToLockscreenTransitionViewModel, lockscreenToOccludedTransitionViewModel: LockscreenToOccludedTransitionViewModel, + glanceableHubToLockscreenTransitionViewModel: GlanceableHubToLockscreenTransitionViewModel, + lockscreenToGlanceableHubTransitionViewModel: LockscreenToGlanceableHubTransitionViewModel ) { private val statesForConstrainedNotifications = setOf( @@ -87,6 +93,20 @@ constructor( .distinctUntilChanged() .onStart { emit(false) } + private val lockscreenToGlanceableHubRunning = + keyguardTransitionInteractor + .transition(KeyguardState.LOCKSCREEN, KeyguardState.GLANCEABLE_HUB) + .map { it.transitionState == STARTED || it.transitionState == RUNNING } + .distinctUntilChanged() + .onStart { emit(false) } + + private val glanceableHubToLockscreenRunning = + keyguardTransitionInteractor + .transition(KeyguardState.GLANCEABLE_HUB, KeyguardState.LOCKSCREEN) + .map { it.transitionState == STARTED || it.transitionState == RUNNING } + .distinctUntilChanged() + .onStart { emit(false) } + val shadeCollapseFadeInComplete = MutableStateFlow(false) val configurationBasedDimensions: Flow<ConfigurationBasedDimensions> = @@ -144,6 +164,24 @@ constructor( initialValue = false, ) + /** Are we purely on the glanceable hub without the shade/qs? */ + internal val isOnGlanceableHubWithoutShade: Flow<Boolean> = + combine( + communalInteractor.isIdleOnCommunal, + // Shade with notifications + shadeInteractor.shadeExpansion.map { it > 0f }, + // Shade without notifications, quick settings only (pull down from very top on + // lockscreen) + shadeInteractor.qsExpansion.map { it > 0f }, + ) { isIdleOnCommunal, isShadeVisible, qsExpansion -> + isIdleOnCommunal && !(isShadeVisible || qsExpansion) + } + .stateIn( + scope = applicationScope, + started = SharingStarted.WhileSubscribed(), + initialValue = false, + ) + /** Fade in only for use after the shade collapses */ val shadeCollpaseFadeIn: Flow<Boolean> = flow { @@ -201,7 +239,7 @@ constructor( initialValue = NotificationContainerBounds(), ) - val alpha: Flow<Float> = + val expansionAlpha: Flow<Float> = // Due to issues with the legacy shade, some shade expansion events are sent incorrectly, // such as when the shade resets. This can happen while the LOCKSCREEN<->OCCLUDED transition // is running. Therefore use a series of flatmaps to prevent unwanted interruptions while @@ -235,6 +273,43 @@ constructor( } /** + * Returns a flow of the expected alpha while running a LOCKSCREEN<->GLANCEABLE_HUB transition + * or idle on the glanceable hub. + * + * Must return 1.0f when not controlling the alpha since notifications does a min of all the + * alpha sources. + */ + val glanceableHubAlpha: Flow<Float> = + isOnGlanceableHubWithoutShade.flatMapLatest { isOnGlanceableHubWithoutShade -> + combineTransform( + lockscreenToGlanceableHubRunning, + glanceableHubToLockscreenRunning, + merge( + lockscreenToGlanceableHubTransitionViewModel.notificationAlpha, + glanceableHubToLockscreenTransitionViewModel.notificationAlpha, + ) + .onStart { + // Transition flows don't emit a value on start, kick things off so the + // combine starts. + emit(1f) + } + ) { lockscreenToGlanceableHubRunning, glanceableHubToLockscreenRunning, alpha -> + if (isOnGlanceableHubWithoutShade) { + // Notifications should not be visible on the glanceable hub. + // TODO(b/321075734): implement a way to actually set the notifications to gone + // while on the hub instead of just adjusting alpha + emit(0f) + } else if (lockscreenToGlanceableHubRunning || glanceableHubToLockscreenRunning) { + emit(alpha) + } else { + // Not on the hub and no transitions running, return full visibility so we don't + // block the notifications from showing. + emit(1f) + } + } + } + + /** * Under certain scenarios, such as swiping up on the lockscreen, the container will need to be * translated as the keyguard fades out. */ 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 ae04eaf49b65..aabe4a0d66f9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java @@ -60,6 +60,7 @@ import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dock.DockManager; import com.android.systemui.keyguard.KeyguardUnlockAnimationController; +import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor; import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor; import com.android.systemui.keyguard.shared.model.ScrimAlpha; import com.android.systemui.keyguard.shared.model.TransitionState; @@ -217,6 +218,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump private final ScreenOffAnimationController mScreenOffAnimationController; private final KeyguardUnlockAnimationController mKeyguardUnlockAnimationController; private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; + private final KeyguardInteractor mKeyguardInteractor; private GradientColors mColors; private boolean mNeedsDrawableColorUpdate; @@ -298,7 +300,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump DozeParameters dozeParameters, AlarmManager alarmManager, KeyguardStateController keyguardStateController, - DelayedWakeLock.Builder delayedWakeLockBuilder, + DelayedWakeLock.Factory delayedWakeLockFactory, Handler handler, KeyguardUpdateMonitor keyguardUpdateMonitor, DockManager dockManager, @@ -311,6 +313,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump PrimaryBouncerToGoneTransitionViewModel primaryBouncerToGoneTransitionViewModel, AlternateBouncerToGoneTransitionViewModel alternateBouncerToGoneTransitionViewModel, KeyguardTransitionInteractor keyguardTransitionInteractor, + KeyguardInteractor keyguardInteractor, WallpaperRepository wallpaperRepository, @Main CoroutineDispatcher mainDispatcher, LargeScreenShadeInterpolator largeScreenShadeInterpolator) { @@ -328,7 +331,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump mScreenOffAnimationController = screenOffAnimationController; mTimeTicker = new AlarmTimeout(alarmManager, this::onHideWallpaperTimeout, "hide_aod_wallpaper", mHandler); - mWakeLock = delayedWakeLockBuilder.setHandler(mHandler).setTag("Scrims").build(); + mWakeLock = delayedWakeLockFactory.create("Scrims"); // Scrim alpha is initially set to the value on the resource but might be changed // to make sure that text on top of it is legible. mDozeParameters = dozeParameters; @@ -357,6 +360,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump mPrimaryBouncerToGoneTransitionViewModel = primaryBouncerToGoneTransitionViewModel; mAlternateBouncerToGoneTransitionViewModel = alternateBouncerToGoneTransitionViewModel; mKeyguardTransitionInteractor = keyguardTransitionInteractor; + mKeyguardInteractor = keyguardInteractor; mWallpaperRepository = wallpaperRepository; mMainDispatcher = mainDispatcher; } @@ -759,7 +763,9 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump // see: b/186644628 mNotificationsScrim.setDrawableBounds(left - 1, top, right + 1, bottom); mScrimBehind.setBottomEdgePosition((int) top); + mKeyguardInteractor.setTopClippingBounds((int) top); } else { + mKeyguardInteractor.setTopClippingBounds(null); mNotificationsScrim.setDrawableBounds(left, top, right, bottom); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/OemSatelliteInputLog.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/OemSatelliteInputLog.kt new file mode 100644 index 000000000000..252945f1ed6a --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/OemSatelliteInputLog.kt @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.pipeline.dagger + +import com.android.systemui.statusbar.pipeline.satellite.data.DeviceBasedSatelliteRepository +import javax.inject.Qualifier + +/** Detailed [DeviceBasedSatelliteRepository] logs */ +@Qualifier +@MustBeDocumented +@kotlin.annotation.Retention(AnnotationRetention.RUNTIME) +annotation class OemSatelliteInputLog diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt index e309c32df64e..2b90e649a154 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt @@ -265,6 +265,13 @@ abstract class StatusBarPipelineModule { return factory.create("VerboseMobileViewLog", 100) } + @Provides + @SysUISingleton + @OemSatelliteInputLog + fun provideOemSatelliteInputLog(factory: LogBufferFactory): LogBuffer { + return factory.create("DeviceBasedSatelliteInputLog", 32) + } + const val FIRST_MOBILE_SUB_SHOWING_NETWORK_TYPE_ICON = "FirstMobileSubShowingNetworkTypeIcon" } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/icons/shared/BindableIconsRegistry.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/icons/shared/BindableIconsRegistry.kt index e3c3139f6906..8400fb08e147 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/icons/shared/BindableIconsRegistry.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/icons/shared/BindableIconsRegistry.kt @@ -18,6 +18,7 @@ package com.android.systemui.statusbar.pipeline.icons.shared import com.android.systemui.dagger.SysUISingleton import com.android.systemui.statusbar.pipeline.icons.shared.model.BindableIcon +import com.android.systemui.statusbar.pipeline.satellite.ui.DeviceBasedSatelliteBindableIcon import javax.inject.Inject /** @@ -38,11 +39,12 @@ interface BindableIconsRegistry { class BindableIconsRegistryImpl @Inject constructor( -/** Bindables go here */ + /** Bindables go here */ + oemSatellite: DeviceBasedSatelliteBindableIcon ) : BindableIconsRegistry { /** * Adding the injected bindables to this list will get them registered with * StatusBarIconController */ - override val bindableIcons: List<BindableIcon> = listOf() + override val bindableIcons: List<BindableIcon> = listOf(oemSatellite) } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileConnectionRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileConnectionRepository.kt index bc38b538f8c0..a608be39f7f7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileConnectionRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileConnectionRepository.kt @@ -72,6 +72,9 @@ interface MobileConnectionRepository { */ val isInService: StateFlow<Boolean> + /** Reflects [android.telephony.ServiceState.isUsingNonTerrestrialNetwork] */ + val isNonTerrestrial: StateFlow<Boolean> + /** True if [android.telephony.SignalStrength] told us that this connection is using GSM */ val isGsm: StateFlow<Boolean> diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionRepository.kt index b2a773375cd5..6de7a00b5a10 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionRepository.kt @@ -32,6 +32,7 @@ import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullM import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_EMERGENCY import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_IS_GSM import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_IS_IN_SERVICE +import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_IS_NTN import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_OPERATOR import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_PRIMARY_LEVEL import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Companion.COL_ROAMING @@ -109,6 +110,17 @@ class DemoMobileConnectionRepository( ) .stateIn(scope, SharingStarted.WhileSubscribed(), _isInService.value) + private val _isNonTerrestrial = MutableStateFlow(false) + override val isNonTerrestrial = + _isNonTerrestrial + .logDiffsForTable( + tableLogBuffer, + columnPrefix = "", + columnName = COL_IS_NTN, + _isNonTerrestrial.value + ) + .stateIn(scope, SharingStarted.WhileSubscribed(), _isNonTerrestrial.value) + private val _isGsm = MutableStateFlow(false) override val isGsm = _isGsm @@ -227,6 +239,7 @@ class DemoMobileConnectionRepository( (event.activity ?: TelephonyManager.DATA_ACTIVITY_NONE).toMobileDataActivityModel() _carrierNetworkChangeActive.value = event.carrierNetworkChange _resolvedNetworkType.value = resolvedNetworkType + _isNonTerrestrial.value = event.ntn isAllowedDuringAirplaneMode.value = false hasPrioritizedNetworkCapabilities.value = event.slice diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoModeMobileConnectionDataSource.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoModeMobileConnectionDataSource.kt index 4cd877eb1a14..11a61a9fd319 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoModeMobileConnectionDataSource.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoModeMobileConnectionDataSource.kt @@ -77,6 +77,7 @@ constructor( val roaming = getString("roam") == "show" val name = getString("networkname") ?: "demo mode" val slice = getString("slice").toBoolean() + val ntn = getString("ntn").toBoolean() return Mobile( level = level, @@ -89,6 +90,7 @@ constructor( roaming = roaming, name = name, slice = slice, + ntn = ntn, ) } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/model/FakeNetworkEventModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/model/FakeNetworkEventModel.kt index 0aa95f8821cc..4836abe73f86 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/model/FakeNetworkEventModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/model/FakeNetworkEventModel.kt @@ -37,6 +37,7 @@ sealed interface FakeNetworkEventModel { val roaming: Boolean, val name: String, val slice: Boolean = false, + val ntn: Boolean = false, ) : FakeNetworkEventModel data class MobileDisabled( diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepository.kt index e5a5695d3655..f8858c5037ab 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepository.kt @@ -168,6 +168,7 @@ class CarrierMergedConnectionRepository( override val isEmergencyOnly = MutableStateFlow(false).asStateFlow() override val operatorAlphaShort = MutableStateFlow(null).asStateFlow() override val isInService = MutableStateFlow(true).asStateFlow() + override val isNonTerrestrial = MutableStateFlow(false).asStateFlow() override val isGsm = MutableStateFlow(false).asStateFlow() override val carrierNetworkChangeActive = MutableStateFlow(false).asStateFlow() diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepository.kt index 48bf7ac60ba7..a1241965de7a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepository.kt @@ -175,6 +175,21 @@ class FullMobileConnectionRepository( ) .stateIn(scope, SharingStarted.WhileSubscribed(), activeRepo.value.isInService.value) + override val isNonTerrestrial = + activeRepo + .flatMapLatest { it.isNonTerrestrial } + .logDiffsForTable( + tableLogBuffer, + columnPrefix = "", + columnName = COL_IS_NTN, + activeRepo.value.isNonTerrestrial.value + ) + .stateIn( + scope, + SharingStarted.WhileSubscribed(), + activeRepo.value.isNonTerrestrial.value + ) + override val isGsm = activeRepo .flatMapLatest { it.isGsm } @@ -366,6 +381,7 @@ class FullMobileConnectionRepository( const val COL_CARRIER_NETWORK_CHANGE = "carrierNetworkChangeActive" const val COL_CDMA_LEVEL = "cdmaLevel" const val COL_EMERGENCY = "emergencyOnly" + const val COL_IS_NTN = "isNtn" const val COL_IS_GSM = "isGsm" const val COL_IS_IN_SERVICE = "isInService" const val COL_OPERATOR = "operatorName" diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt index f44401ba4702..77fd6bef8a33 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt @@ -227,6 +227,12 @@ class MobileConnectionRepositoryImpl( .map { Utils.isInService(it.serviceState) } .stateIn(scope, SharingStarted.WhileSubscribed(), false) + override val isNonTerrestrial = + callbackEvents + .mapNotNull { it.onServiceStateChanged } + .map { it.serviceState.isUsingNonTerrestrialNetwork } + .stateIn(scope, SharingStarted.WhileSubscribed(), false) + override val isGsm = callbackEvents .mapNotNull { it.onSignalStrengthChanged } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImpl.kt index de46a5ed99d6..0e6775685611 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImpl.kt @@ -19,11 +19,18 @@ package com.android.systemui.statusbar.pipeline.satellite.data.prod import android.os.OutcomeReceiver import android.telephony.satellite.NtnSignalStrengthCallback import android.telephony.satellite.SatelliteManager +import android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCCESS import android.telephony.satellite.SatelliteModemStateCallback +import androidx.annotation.VisibleForTesting import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Background +import com.android.systemui.log.LogBuffer +import com.android.systemui.log.core.LogLevel +import com.android.systemui.log.core.MessageInitializer +import com.android.systemui.log.core.MessagePrinter +import com.android.systemui.statusbar.pipeline.dagger.OemSatelliteInputLog import com.android.systemui.statusbar.pipeline.satellite.data.DeviceBasedSatelliteRepository import com.android.systemui.statusbar.pipeline.satellite.data.prod.SatelliteSupport.Companion.whenSupported import com.android.systemui.statusbar.pipeline.satellite.data.prod.SatelliteSupport.NotSupported @@ -62,8 +69,10 @@ private typealias SupportedSatelliteManager = SatelliteManager /** * "Supported" here means supported by the device. The value of this should be stable during the * process lifetime. + * + * @VisibleForTesting */ -private sealed interface SatelliteSupport { +sealed interface SatelliteSupport { /** Not yet fetched */ data object Unknown : SatelliteSupport @@ -123,6 +132,7 @@ constructor( satelliteManagerOpt: Optional<SatelliteManager>, @Background private val bgDispatcher: CoroutineDispatcher, @Application private val scope: CoroutineScope, + @OemSatelliteInputLog private val logBuffer: LogBuffer, private val systemClock: SystemClock, ) : DeviceBasedSatelliteRepository { @@ -132,7 +142,8 @@ constructor( // Some calls into satellite manager will throw exceptions if it is not supported. // This is never expected to change after boot, but may need to be retried in some cases - private val satelliteSupport: MutableStateFlow<SatelliteSupport> = MutableStateFlow(Unknown) + @get:VisibleForTesting + val satelliteSupport: MutableStateFlow<SatelliteSupport> = MutableStateFlow(Unknown) init { satelliteManager = satelliteManagerOpt.getOrNull() @@ -145,6 +156,11 @@ constructor( ensureMinUptime(systemClock, MIN_UPTIME) satelliteSupport.value = satelliteManager.checkSatelliteSupported() + logBuffer.i( + { str1 = satelliteSupport.value.toString() }, + { "Checked for system support. support=$str1" }, + ) + // We only need to check location availability if this mode is supported if (satelliteSupport.value is Supported) { isSatelliteAllowedForCurrentLocation.subscriptionCount @@ -159,6 +175,9 @@ constructor( * connection might cause more frequent checks. */ while (true) { + logBuffer.i { + "requestIsSatelliteCommunicationAllowedForCurrentLocation" + } checkIsSatelliteAllowed() delay(POLLING_INTERVAL_MS) } @@ -167,6 +186,8 @@ constructor( } } } else { + logBuffer.i { "Satellite manager is null" } + satelliteSupport.value = NotSupported } } @@ -181,12 +202,21 @@ constructor( private fun connectionStateFlow(sm: SupportedSatelliteManager): Flow<SatelliteConnectionState> = conflatedCallbackFlow { val cb = SatelliteModemStateCallback { state -> + logBuffer.i({ int1 = state }) { "onSatelliteModemStateChanged: state=$int1" } trySend(SatelliteConnectionState.fromModemState(state)) } - sm.registerForSatelliteModemStateChanged(bgDispatcher.asExecutor(), cb) + var registered = false - awaitClose { sm.unregisterForSatelliteModemStateChanged(cb) } + try { + val res = + sm.registerForSatelliteModemStateChanged(bgDispatcher.asExecutor(), cb) + registered = res == SATELLITE_RESULT_SUCCESS + } catch (e: Exception) { + logBuffer.e("error registering for modem state", e) + } + + awaitClose { if (registered) sm.unregisterForSatelliteModemStateChanged(cb) } } .flowOn(bgDispatcher) @@ -197,12 +227,21 @@ constructor( private fun signalStrengthFlow(sm: SupportedSatelliteManager) = conflatedCallbackFlow { val cb = NtnSignalStrengthCallback { signalStrength -> + logBuffer.i({ int1 = signalStrength.level }) { + "onNtnSignalStrengthChanged: level=$int1" + } trySend(signalStrength.level) } - sm.registerForNtnSignalStrengthChanged(bgDispatcher.asExecutor(), cb) + var registered = false + try { + sm.registerForNtnSignalStrengthChanged(bgDispatcher.asExecutor(), cb) + registered = true + } catch (e: Exception) { + logBuffer.e("error registering for signal strength", e) + } - awaitClose { sm.unregisterForNtnSignalStrengthChanged(cb) } + awaitClose { if (registered) sm.unregisterForNtnSignalStrengthChanged(cb) } } .flowOn(bgDispatcher) @@ -213,11 +252,15 @@ constructor( bgDispatcher.asExecutor(), object : OutcomeReceiver<Boolean, SatelliteManager.SatelliteException> { override fun onError(e: SatelliteManager.SatelliteException) { - android.util.Log.e(TAG, "Found exception when checking for satellite: ", e) + logBuffer.e( + "Found exception when checking availability", + e, + ) isSatelliteAllowedForCurrentLocation.value = false } override fun onResult(allowed: Boolean) { + logBuffer.i { allowed.toString() } isSatelliteAllowedForCurrentLocation.value = allowed } } @@ -239,12 +282,27 @@ constructor( } override fun onError(error: SatelliteManager.SatelliteException) { + logBuffer.e( + "Exception when checking for satellite support. " + + "Assuming it is not supported for this device.", + error, + ) + // Assume that an error means it's not supported continuation.resume(NotSupported) } } - requestIsSatelliteSupported(bgDispatcher.asExecutor(), cb) + try { + requestIsSatelliteSupported(bgDispatcher.asExecutor(), cb) + } catch (error: Exception) { + logBuffer.e( + "Exception when checking for satellite support. " + + "Assuming it is not supported for this device.", + error, + ) + continuation.resume(NotSupported) + } } companion object { @@ -264,5 +322,19 @@ constructor( delay(timeTilMinUptime) } } + + /** A couple of convenience logging methods rather than a whole class */ + private fun LogBuffer.i( + initializer: MessageInitializer = {}, + printer: MessagePrinter, + ) = this.log(TAG, LogLevel.INFO, initializer, printer) + + private fun LogBuffer.e(message: String, exception: Throwable? = null) = + this.log( + tag = TAG, + level = LogLevel.ERROR, + message = message, + exception = exception, + ) } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/ui/DeviceBasedSatelliteBindableIcon.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/ui/DeviceBasedSatelliteBindableIcon.kt new file mode 100644 index 000000000000..f5d0f6b8f07c --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/ui/DeviceBasedSatelliteBindableIcon.kt @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.pipeline.satellite.ui + +import android.content.Context +import com.android.internal.telephony.flags.Flags.oemEnabledSatelliteFlag +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.statusbar.pipeline.icons.shared.model.BindableIcon +import com.android.systemui.statusbar.pipeline.icons.shared.model.ModernStatusBarViewCreator +import com.android.systemui.statusbar.pipeline.satellite.ui.binder.DeviceBasedSatelliteIconBinder +import com.android.systemui.statusbar.pipeline.satellite.ui.viewmodel.DeviceBasedSatelliteViewModel +import com.android.systemui.statusbar.pipeline.shared.ui.view.SingleBindableStatusBarIconView +import javax.inject.Inject + +@SysUISingleton +class DeviceBasedSatelliteBindableIcon +@Inject +constructor( + context: Context, + viewModel: DeviceBasedSatelliteViewModel, +) : BindableIcon { + override val slot: String = + context.getString(com.android.internal.R.string.status_bar_oem_satellite) + + override val initializer = ModernStatusBarViewCreator { context -> + SingleBindableStatusBarIconView.createView(context).also { view -> + view.initView(slot) { DeviceBasedSatelliteIconBinder.bind(view, viewModel) } + } + } + + override val shouldBindIcon: Boolean = oemEnabledSatelliteFlag() +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/ui/binder/DeviceBasedSatelliteIconBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/ui/binder/DeviceBasedSatelliteIconBinder.kt new file mode 100644 index 000000000000..59ac5f29b66c --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/ui/binder/DeviceBasedSatelliteIconBinder.kt @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.pipeline.satellite.ui.binder + +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.lifecycleScope +import androidx.lifecycle.repeatOnLifecycle +import com.android.systemui.common.ui.binder.IconViewBinder +import com.android.systemui.statusbar.pipeline.satellite.ui.viewmodel.DeviceBasedSatelliteViewModel +import com.android.systemui.statusbar.pipeline.shared.ui.binder.ModernStatusBarViewBinding +import com.android.systemui.statusbar.pipeline.shared.ui.view.SingleBindableStatusBarIconView +import kotlinx.coroutines.launch + +object DeviceBasedSatelliteIconBinder { + fun bind( + view: SingleBindableStatusBarIconView, + viewModel: DeviceBasedSatelliteViewModel, + ): ModernStatusBarViewBinding { + return SingleBindableStatusBarIconView.withDefaultBinding( + view = view, + shouldBeVisible = { viewModel.icon.value != null } + ) { + lifecycleScope.launch { + repeatOnLifecycle(Lifecycle.State.STARTED) { + viewModel.icon.collect { newIcon -> + if (newIcon == null) { + view.iconView.setImageDrawable(null) + } else { + IconViewBinder.bind(newIcon, view.iconView) + } + } + } + } + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/ui/model/SatelliteIconModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/ui/model/SatelliteIconModel.kt new file mode 100644 index 000000000000..6938d667ca81 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/ui/model/SatelliteIconModel.kt @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.pipeline.satellite.ui.model + +import com.android.systemui.common.shared.model.Icon +import com.android.systemui.res.R +import com.android.systemui.statusbar.pipeline.satellite.shared.model.SatelliteConnectionState + +/** + * Define the [Icon] that relates to a given satellite connection state + level. Note that for now + * We don't need any data class box, so we can just use a simple mapping function. + */ +object SatelliteIconModel { + fun fromConnectionState( + connectionState: SatelliteConnectionState, + signalStrength: Int, + ): Icon? = + when (connectionState) { + // TODO(b/316635648): check if this should be null + SatelliteConnectionState.Unknown, + SatelliteConnectionState.Off, + SatelliteConnectionState.On -> + Icon.Resource( + res = R.drawable.ic_satellite_not_connected, + contentDescription = null, + ) + SatelliteConnectionState.Connected -> fromSignalStrength(signalStrength) + } + + private fun fromSignalStrength( + signalStrength: Int, + ): Icon? = + // TODO(b/316634365): these need content descriptions + when (signalStrength) { + // No signal + 0 -> Icon.Resource(res = R.drawable.ic_satellite_connected_0, contentDescription = null) + + // Poor -> Moderate + 1, + 2 -> Icon.Resource(res = R.drawable.ic_satellite_connected_1, contentDescription = null) + + // Good -> Great + 3, + 4 -> Icon.Resource(res = R.drawable.ic_satellite_connected_2, contentDescription = null) + else -> null + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModel.kt new file mode 100644 index 000000000000..0051161eff35 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModel.kt @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.pipeline.satellite.ui.viewmodel + +import com.android.systemui.common.shared.model.Icon +import com.android.systemui.dagger.qualifiers.Application +import com.android.systemui.statusbar.pipeline.satellite.domain.interactor.DeviceBasedSatelliteInteractor +import com.android.systemui.statusbar.pipeline.satellite.ui.model.SatelliteIconModel +import javax.inject.Inject +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.flow.stateIn + +/** + * View-Model for the device-based satellite icon. This icon will only show in the status bar if + * satellite is available AND all other service states are considered OOS. + */ +@OptIn(ExperimentalCoroutinesApi::class) +class DeviceBasedSatelliteViewModel +@Inject +constructor( + interactor: DeviceBasedSatelliteInteractor, + @Application scope: CoroutineScope, +) { + private val shouldShowIcon: StateFlow<Boolean> = + interactor.areAllConnectionsOutOfService + .flatMapLatest { allOos -> + if (!allOos) { + flowOf(false) + } else { + interactor.isSatelliteAllowed + } + } + .stateIn(scope, SharingStarted.WhileSubscribed(), false) + + val icon: StateFlow<Icon?> = + combine( + shouldShowIcon, + interactor.connectionState, + interactor.signalStrength, + ) { shouldShow, state, signalStrength -> + if (shouldShow) { + SatelliteIconModel.fromConnectionState(state, signalStrength) + } else { + null + } + } + .stateIn(scope, SharingStarted.WhileSubscribed(), null) +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/view/ModernStatusBarView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/view/ModernStatusBarView.kt index 3b87bed2e0ef..25a2c9dd3caf 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/view/ModernStatusBarView.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/view/ModernStatusBarView.kt @@ -103,7 +103,7 @@ open class ModernStatusBarView(context: Context, attrs: AttributeSet?) : * * Creates a dot view, and uses [bindingCreator] to get and set the binding. */ - fun initView(slot: String, bindingCreator: () -> ModernStatusBarViewBinding) { + open fun initView(slot: String, bindingCreator: () -> ModernStatusBarViewBinding) { // The dot view requires [slot] to be set, and the [binding] may require an instantiated dot // view. So, this is the required order. this.slot = slot diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/view/SingleBindableStatusBarIconView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/view/SingleBindableStatusBarIconView.kt new file mode 100644 index 000000000000..c663c37fec98 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/view/SingleBindableStatusBarIconView.kt @@ -0,0 +1,184 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.pipeline.shared.ui.view + +import android.content.Context +import android.content.res.ColorStateList +import android.graphics.Color +import android.util.AttributeSet +import android.view.LayoutInflater +import android.view.View +import android.widget.ImageView +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.LifecycleOwner +import androidx.lifecycle.lifecycleScope +import androidx.lifecycle.repeatOnLifecycle +import com.android.internal.annotations.VisibleForTesting +import com.android.systemui.lifecycle.repeatWhenAttached +import com.android.systemui.res.R +import com.android.systemui.statusbar.StatusBarIconView +import com.android.systemui.statusbar.StatusBarIconView.STATE_HIDDEN +import com.android.systemui.statusbar.pipeline.shared.ui.binder.ModernStatusBarViewBinding +import com.android.systemui.statusbar.pipeline.shared.ui.binder.ModernStatusBarViewVisibilityHelper +import kotlinx.coroutines.awaitCancellation +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.launch + +/** Simple single-icon view that is bound to bindable_status_bar_icon.xml */ +class SingleBindableStatusBarIconView( + context: Context, + attrs: AttributeSet?, +) : ModernStatusBarView(context, attrs) { + + internal lateinit var iconView: ImageView + internal lateinit var dotView: StatusBarIconView + + override fun toString(): String { + return "SingleBindableStatusBarIcon(" + + "slot='$slot', " + + "isCollecting=${binding.isCollecting()}, " + + "visibleState=${StatusBarIconView.getVisibleStateString(visibleState)}); " + + "viewString=${super.toString()}" + } + + override fun initView(slot: String, bindingCreator: () -> ModernStatusBarViewBinding) { + super.initView(slot, bindingCreator) + + iconView = requireViewById(R.id.icon_view) + dotView = requireViewById(R.id.status_bar_dot) + } + + companion object { + fun createView( + context: Context, + ): SingleBindableStatusBarIconView { + return LayoutInflater.from(context).inflate(R.layout.bindable_status_bar_icon, null) + as SingleBindableStatusBarIconView + } + + /** + * Using a given binding [block], create the necessary scaffolding to handle the general + * case of a single status bar icon. This includes eliding into a dot view when there is not + * enough space, and handling tint. + * + * [block] should be a simple [launch] call that handles updating the single icon view with + * its new view. Currently there is no simple way to e.g., extend to handle multiple tints + * for dual-layered icons, and any more complex logic should probably find a way to return + * its own version of [ModernStatusBarViewBinding]. + */ + fun withDefaultBinding( + view: SingleBindableStatusBarIconView, + shouldBeVisible: () -> Boolean, + block: suspend LifecycleOwner.(View) -> Unit + ): SingleBindableStatusBarIconViewBinding { + @StatusBarIconView.VisibleState + val visibilityState: MutableStateFlow<Int> = MutableStateFlow(STATE_HIDDEN) + + val iconTint: MutableStateFlow<Int> = MutableStateFlow(Color.WHITE) + val decorTint: MutableStateFlow<Int> = MutableStateFlow(Color.WHITE) + + var isCollecting: Boolean = false + + view.repeatWhenAttached { + // Child binding + block(view) + + lifecycleScope.launch { + repeatOnLifecycle(Lifecycle.State.STARTED) { + // isVisible controls the visibility state of the outer group, and thus it + // needs + // to run in the CREATED lifecycle so it can continue to watch while + // invisible + // See (b/291031862) for details + launch { + visibilityState.collect { visibilityState -> + // for b/296864006, we can not hide all the child views if + // visibilityState is STATE_HIDDEN. Because hiding all child views + // would cause the + // getWidth() of this view return 0, and that would cause the + // translation + // calculation fails in StatusIconContainer. Therefore, like class + // MobileIconBinder, instead of set the child views visibility to + // View.GONE, + // we set their visibility to View.INVISIBLE to make them invisible + // but + // keep the width. + ModernStatusBarViewVisibilityHelper.setVisibilityState( + visibilityState, + view.iconView, + view.dotView, + ) + } + } + + launch { + iconTint.collect { tint -> + val tintList = ColorStateList.valueOf(tint) + view.iconView.imageTintList = tintList + view.dotView.setDecorColor(tint) + } + } + + launch { + decorTint.collect { decorTint -> view.dotView.setDecorColor(decorTint) } + } + + try { + awaitCancellation() + } finally { + isCollecting = false + } + } + } + } + + return object : SingleBindableStatusBarIconViewBinding { + override val decorTint: Int + get() = decorTint.value + + override val iconTint: Int + get() = iconTint.value + + override fun getShouldIconBeVisible(): Boolean { + return shouldBeVisible() + } + + override fun onVisibilityStateChanged(state: Int) { + visibilityState.value = state + } + + override fun onIconTintChanged(newTint: Int, contrastTint: Int) { + iconTint.value = newTint + } + + override fun onDecorTintChanged(newTint: Int) { + decorTint.value = newTint + } + + override fun isCollecting(): Boolean { + return isCollecting + } + } + } + } +} + +@VisibleForTesting +interface SingleBindableStatusBarIconViewBinding : ModernStatusBarViewBinding { + val iconTint: Int + val decorTint: Int +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BaseHeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BaseHeadsUpManager.java index 1528c9befda7..1414150c5511 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BaseHeadsUpManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BaseHeadsUpManager.java @@ -159,7 +159,7 @@ public abstract class BaseHeadsUpManager implements HeadsUpManager { public void showNotification(@NonNull NotificationEntry entry) { mLogger.logShowNotification(entry); addEntry(entry); - updateNotification(entry.getKey(), true /* show */); + updateNotification(entry.getKey(), true /* shouldHeadsUpAgain */); entry.setInterruption(); } @@ -190,12 +190,12 @@ public abstract class BaseHeadsUpManager implements HeadsUpManager { /** * Called when the notification state has been updated. * @param key the key of the entry that was updated - * @param show whether the notification should show again and force reevaluation of - * removal time + * @param shouldHeadsUpAgain whether the notification should show again and force reevaluation + * of removal time */ - public void updateNotification(@NonNull String key, boolean show) { + public void updateNotification(@NonNull String key, boolean shouldHeadsUpAgain) { HeadsUpEntry headsUpEntry = mHeadsUpEntryMap.get(key); - mLogger.logUpdateNotification(key, show, headsUpEntry != null); + mLogger.logUpdateNotification(key, shouldHeadsUpAgain, headsUpEntry != null); if (headsUpEntry == null) { // the entry was released before this update (i.e by a listener) This can happen // with the groupmanager @@ -204,7 +204,7 @@ public abstract class BaseHeadsUpManager implements HeadsUpManager { headsUpEntry.mEntry.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED); - if (show) { + if (shouldHeadsUpAgain) { headsUpEntry.updateEntry(true /* updatePostTime */, "updateNotification"); if (headsUpEntry != null) { setEntryPinned(headsUpEntry, shouldHeadsUpBecomePinned(headsUpEntry.mEntry)); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.kt index b8c7e202ce7c..a7352be8d80a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.kt @@ -182,7 +182,7 @@ interface HeadsUpManager : Dumpable { */ fun unpinAll(userUnPinned: Boolean) - fun updateNotification(key: String, alert: Boolean) + fun updateNotification(key: String, shouldHeadsUpAgain: Boolean) } /** Sets the animation state of the HeadsUpManager. */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionController.java new file mode 100644 index 000000000000..970cc75bbb6b --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionController.java @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.policy; + +import com.android.systemui.statusbar.notification.collection.NotificationEntry; + +/** + * A controller which provides the current sensitive notification protections status as well as + * to assist in feature usage and exemptions + */ +public interface SensitiveNotificationProtectionController { + /** + * Register a runnable that triggers on changes to protection state + * + * <p> onSensitiveStateChanged not invoked on registration + */ + void registerSensitiveStateListener(Runnable onSensitiveStateChanged); + + /** Unregister a previously registered onSensitiveStateChanged runnable */ + void unregisterSensitiveStateListener(Runnable onSensitiveStateChanged); + + /** Return {@code true} if device in state in which notifications should be protected */ + boolean isSensitiveStateActive(); + + /** Return {@code true} when notification should be protected */ + boolean shouldProtectNotification(NotificationEntry entry); +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerImpl.java new file mode 100644 index 000000000000..3c4ca4465874 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerImpl.java @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.policy; + +import static com.android.systemui.Flags.screenshareNotificationHiding; + +import android.media.projection.MediaProjectionInfo; +import android.media.projection.MediaProjectionManager; +import android.os.Handler; +import android.os.Trace; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.systemui.dagger.SysUISingleton; +import com.android.systemui.dagger.qualifiers.Main; +import com.android.systemui.statusbar.notification.collection.NotificationEntry; +import com.android.systemui.util.ListenerSet; + +import javax.inject.Inject; + +/** Implementation of SensitiveNotificationProtectionController. **/ +@SysUISingleton +public class SensitiveNotificationProtectionControllerImpl + implements SensitiveNotificationProtectionController { + private final MediaProjectionManager mMediaProjectionManager; + private final ListenerSet<Runnable> mListeners = new ListenerSet<>(); + private volatile MediaProjectionInfo mProjection; + + @VisibleForTesting + final MediaProjectionManager.Callback mMediaProjectionCallback = + new MediaProjectionManager.Callback() { + @Override + public void onStart(MediaProjectionInfo info) { + Trace.beginSection( + "SNPC.onProjectionStart"); + mProjection = info; + mListeners.forEach(Runnable::run); + Trace.endSection(); + } + + @Override + public void onStop(MediaProjectionInfo info) { + Trace.beginSection( + "SNPC.onProjectionStop"); + mProjection = null; + mListeners.forEach(Runnable::run); + Trace.endSection(); + } + }; + + @Inject + public SensitiveNotificationProtectionControllerImpl( + MediaProjectionManager mediaProjectionManager, + @Main Handler mainHandler) { + mMediaProjectionManager = mediaProjectionManager; + + if (screenshareNotificationHiding()) { + mMediaProjectionManager.addCallback(mMediaProjectionCallback, mainHandler); + } + } + + @Override + public void registerSensitiveStateListener(Runnable onSensitiveStateChanged) { + mListeners.addIfAbsent(onSensitiveStateChanged); + } + + @Override + public void unregisterSensitiveStateListener(Runnable onSensitiveStateChanged) { + mListeners.remove(onSensitiveStateChanged); + } + + @Override + public boolean isSensitiveStateActive() { + // TODO(b/316955558): Add disabled by developer option + // TODO(b/316955306): Add feature exemption for sysui and bug handlers + // TODO(b/316955346): Add feature exemption for single app screen sharing + return mProjection != null; + } + + @Override + public boolean shouldProtectNotification(NotificationEntry entry) { + if (!isSensitiveStateActive()) { + return false; + } + + // Exempt foreground service notifications from protection in effort to keep screen share + // stop actions easily accessible + // TODO(b/316955208): Exempt FGS notifications only for app that started projection + return !entry.getSbn().getNotification().isFgsOrUij(); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java index 3304b9827fd8..15200bd0ac54 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java @@ -60,6 +60,8 @@ import com.android.systemui.statusbar.policy.RotationLockController; import com.android.systemui.statusbar.policy.RotationLockControllerImpl; import com.android.systemui.statusbar.policy.SecurityController; import com.android.systemui.statusbar.policy.SecurityControllerImpl; +import com.android.systemui.statusbar.policy.SensitiveNotificationProtectionController; +import com.android.systemui.statusbar.policy.SensitiveNotificationProtectionControllerImpl; import com.android.systemui.statusbar.policy.SplitShadeStateController; import com.android.systemui.statusbar.policy.SplitShadeStateControllerImpl; import com.android.systemui.statusbar.policy.UserInfoController; @@ -146,6 +148,11 @@ public interface StatusBarPolicyModule { /** */ @Binds + SensitiveNotificationProtectionController provideSensitiveNotificationProtectionController( + SensitiveNotificationProtectionControllerImpl controllerImpl); + + /** */ + @Binds UserInfoController provideUserInfoContrller(UserInfoControllerImpl controllerImpl); /** */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ui/SystemBarUtilsState.kt b/packages/SystemUI/src/com/android/systemui/statusbar/ui/SystemBarUtilsState.kt index ce811e205436..10137a0d3430 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ui/SystemBarUtilsState.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ui/SystemBarUtilsState.kt @@ -17,10 +17,16 @@ package com.android.systemui.statusbar.ui import com.android.internal.policy.SystemBarUtils +import com.android.systemui.dagger.qualifiers.Background +import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.statusbar.policy.onConfigChanged import javax.inject.Inject +import kotlin.coroutines.CoroutineContext import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.conflate +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onStart @@ -31,6 +37,8 @@ import kotlinx.coroutines.flow.onStart class SystemBarUtilsState @Inject constructor( + @Background bgContext: CoroutineContext, + @Main mainContext: CoroutineContext, configurationController: ConfigurationController, proxy: SystemBarUtilsProxy, ) { @@ -38,5 +46,10 @@ constructor( val statusBarHeight: Flow<Int> = configurationController.onConfigChanged .onStart<Any> { emit(Unit) } + .flowOn(mainContext) + .conflate() .map { proxy.getStatusBarHeight() } + .distinctUntilChanged() + .flowOn(bgContext) + .conflate() } diff --git a/packages/SystemUI/src/com/android/systemui/util/kotlin/Utils.kt b/packages/SystemUI/src/com/android/systemui/util/kotlin/Utils.kt index 2336a8e46f07..6993c961fba8 100644 --- a/packages/SystemUI/src/com/android/systemui/util/kotlin/Utils.kt +++ b/packages/SystemUI/src/com/android/systemui/util/kotlin/Utils.kt @@ -28,9 +28,13 @@ class Utils { fun <A, B, C, D> toQuad(a: A, bcd: Triple<B, C, D>) = Quad(a, bcd.first, bcd.second, bcd.third) + fun <A, B, C, D, E> toQuint(a: A, b: B, c: C, d: D, e: E) = Quint(a, b, c, d, e) fun <A, B, C, D, E> toQuint(a: A, bcde: Quad<B, C, D, E>) = Quint(a, bcde.first, bcde.second, bcde.third, bcde.fourth) + fun <A, B, C, D, E, F> toSextuple(a: A, bcdef: Quint<B, C, D, E, F>) = + Sextuple(a, bcdef.first, bcdef.second, bcdef.third, bcdef.fourth, bcdef.fifth) + /** * Samples the provided flows, emitting a tuple of the original flow's value as well as each * of the combined flows' values. @@ -69,6 +73,22 @@ class Utils { ): Flow<Quint<A, B, C, D, E>> { return this.sample(combine(b, c, d, e, ::Quad), ::toQuint) } + + /** + * Samples the provided flows, emitting a tuple of the original flow's value as well as each + * of the combined flows' values. + * + * Flow<A>.sample(Flow<B>, Flow<C>, Flow<D>, Flow<E>, Flow<F>) -> (A, B, C, D, E, F) + */ + fun <A, B, C, D, E, F> Flow<A>.sample( + b: Flow<B>, + c: Flow<C>, + d: Flow<D>, + e: Flow<E>, + f: Flow<F>, + ): Flow<Sextuple<A, B, C, D, E, F>> { + return this.sample(combine(b, c, d, e, f, ::Quint), ::toSextuple) + } } } @@ -81,3 +101,12 @@ data class Quint<A, B, C, D, E>( val fourth: D, val fifth: E ) + +data class Sextuple<A, B, C, D, E, F>( + val first: A, + val second: B, + val third: C, + val fourth: D, + val fifth: E, + val sixth: F, +) diff --git a/packages/SystemUI/src/com/android/systemui/util/wakelock/DelayedWakeLock.java b/packages/SystemUI/src/com/android/systemui/util/wakelock/DelayedWakeLock.java index 972895d4a192..039109e9ddc6 100644 --- a/packages/SystemUI/src/com/android/systemui/util/wakelock/DelayedWakeLock.java +++ b/packages/SystemUI/src/com/android/systemui/util/wakelock/DelayedWakeLock.java @@ -19,7 +19,11 @@ package com.android.systemui.util.wakelock; import android.content.Context; import android.os.Handler; -import javax.inject.Inject; +import com.android.systemui.dagger.qualifiers.Background; + +import dagger.assisted.Assisted; +import dagger.assisted.AssistedFactory; +import dagger.assisted.AssistedInject; /** * A wake lock that has a built in delay when releasing to give the framebuffer time to update. @@ -32,9 +36,11 @@ public class DelayedWakeLock implements WakeLock { private final Handler mHandler; private final WakeLock mInner; - public DelayedWakeLock(Handler h, WakeLock inner) { - mHandler = h; - mInner = inner; + @AssistedInject + public DelayedWakeLock(@Background Handler handler, Context context, WakeLockLogger logger, + @Assisted String tag) { + mInner = WakeLock.createPartial(context, logger, tag); + mHandler = handler; } @Override @@ -58,46 +64,11 @@ public class DelayedWakeLock implements WakeLock { } /** - * An injectable builder for {@see DelayedWakeLock} that has the context already filled in. + * Factory to create the instance of DelayedWakeLock class. */ - public static class Builder { - private final Context mContext; - private final WakeLockLogger mLogger; - private String mTag; - private Handler mHandler; - - /** - * Constructor for DelayedWakeLock.Builder - */ - @Inject - public Builder(Context context, WakeLockLogger logger) { - mContext = context; - mLogger = logger; - } - - /** - * Set the tag for the WakeLock. - */ - public Builder setTag(String tag) { - mTag = tag; - - return this; - } - - /** - * Set the handler for the DelayedWakeLock. - */ - public Builder setHandler(Handler handler) { - mHandler = handler; - - return this; - } - - /** - * Build the DelayedWakeLock. - */ - public DelayedWakeLock build() { - return new DelayedWakeLock(mHandler, WakeLock.createPartial(mContext, mLogger, mTag)); - } + @AssistedFactory + public interface Factory { + /** creates the instance of DelayedWakeLock class. */ + DelayedWakeLock create(String tag); } -} +}
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java index 9ee3d220a79b..aee441a13a5d 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java @@ -535,6 +535,7 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa } if (changed && fromKey) { Events.writeEvent(Events.EVENT_KEY, stream, lastAudibleStreamVolume); + mCallbacks.onVolumeChangedFromKey(); } return changed; } @@ -1030,6 +1031,18 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa } @Override + public void onVolumeChangedFromKey() { + for (final Map.Entry<Callbacks, Handler> entry : mCallbackMap.entrySet()) { + entry.getValue().post(new Runnable() { + @Override + public void run() { + entry.getKey().onVolumeChangedFromKey(); + } + }); + } + } + + @Override public void onAccessibilityModeChanged(Boolean showA11yStream) { boolean show = showA11yStream != null && showA11yStream; for (final Map.Entry<Callbacks, Handler> entry : mCallbackMap.entrySet()) { diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java index 404621d1fe81..b127c5160bba 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java @@ -34,6 +34,7 @@ import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; import static com.android.internal.jank.InteractionJankMonitor.CUJ_VOLUME_CONTROL; import static com.android.internal.jank.InteractionJankMonitor.Configuration.Builder; +import static com.android.systemui.Flags.hapticVolumeSlider; import static com.android.systemui.volume.Events.DISMISS_REASON_POSTURE_CHANGED; import static com.android.systemui.volume.Events.DISMISS_REASON_SETTINGS_CLICKED; @@ -117,7 +118,11 @@ import com.android.internal.view.RotationPolicy; import com.android.settingslib.Utils; import com.android.systemui.Dumpable; import com.android.systemui.Prefs; +import com.android.systemui.dagger.qualifiers.Application; +import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dump.DumpManager; +import com.android.systemui.haptics.slider.SeekableSliderHapticPlugin; +import com.android.systemui.haptics.slider.SliderHapticFeedbackConfig; import com.android.systemui.media.dialog.MediaOutputDialogFactory; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.VolumeDialog; @@ -125,6 +130,7 @@ import com.android.systemui.plugins.VolumeDialogController; import com.android.systemui.plugins.VolumeDialogController.State; import com.android.systemui.plugins.VolumeDialogController.StreamState; import com.android.systemui.res.R; +import com.android.systemui.statusbar.VibratorHelper; import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.DevicePostureController; @@ -140,6 +146,9 @@ import java.util.ArrayList; import java.util.List; import java.util.function.Consumer; +import kotlinx.coroutines.CoroutineDispatcher; +import kotlinx.coroutines.CoroutineScope; + /** * Visual presentation of the volume dialog. * @@ -303,6 +312,10 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, private int mOrientation; private final Lazy<SecureSettings> mSecureSettings; private int mDialogTimeoutMillis; + private final CoroutineDispatcher mMainDispatcher; + private final CoroutineScope mApplicationScope; + private final VibratorHelper mVibratorHelper; + private final com.android.systemui.util.time.SystemClock mSystemClock; public VolumeDialogImpl( Context context, @@ -319,11 +332,18 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, DevicePostureController devicePostureController, Looper looper, DumpManager dumpManager, - Lazy<SecureSettings> secureSettings) { + Lazy<SecureSettings> secureSettings, + VibratorHelper vibratorHelper, + @Main CoroutineDispatcher mainDispatcher, + @Application CoroutineScope applicationScope, + com.android.systemui.util.time.SystemClock systemClock) { mContext = new ContextThemeWrapper(context, R.style.volume_dialog_theme); mHandler = new H(looper); - + mMainDispatcher = mainDispatcher; + mApplicationScope = applicationScope; + mVibratorHelper = vibratorHelper; + mSystemClock = systemClock; mShouldListenForJank = shouldListenForJank; mController = volumeDialogController; mKeyguard = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE); @@ -839,6 +859,7 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, row.header.setFilters(new InputFilter[] {new InputFilter.LengthFilter(13)}); } row.slider = row.view.findViewById(R.id.volume_row_slider); + row.createPlugin(mVibratorHelper, mSystemClock, mMainDispatcher, mApplicationScope); row.slider.setOnSeekBarChangeListener(new VolumeSeekBarChangeListener(row)); row.number = row.view.findViewById(R.id.volume_number); @@ -1480,6 +1501,12 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, mController.getCaptionsComponentState(false); checkODICaptionsTooltip(false); updateBackgroundForDrawerClosedAmount(); + for (int i = 0; i < mRows.size(); i++) { + VolumeRow row = mRows.get(i); + if (row.slider.getVisibility() == VISIBLE) { + row.addHaptics(); + } + } Trace.endSection(); } @@ -1532,7 +1559,9 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, protected void dismissH(int reason) { Trace.beginSection("VolumeDialogImpl#dismissH"); - + for (int i = 0; i < mRows.size(); i++) { + mRows.get(i).removeHaptics(); + } Log.i(TAG, "mDialog.dismiss() reason: " + Events.DISMISS_REASONS[reason] + " from: " + Debug.getCaller()); @@ -2358,6 +2387,14 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, public void onCaptionEnabledStateChanged(Boolean isEnabled, Boolean checkForSwitchState) { updateCaptionsEnabledH(isEnabled, checkForSwitchState); } + + @Override + public void onVolumeChangedFromKey() { + VolumeRow activeRow = getActiveRow(); + if (activeRow.mHapticPlugin != null) { + activeRow.mHapticPlugin.onKeyDown(); + } + } }; @VisibleForTesting void onPostureChanged(int posture) { @@ -2459,6 +2496,15 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { if (mRow.ss == null) return; + if (getActiveRow().equals(mRow) + && mRow.slider.getVisibility() == VISIBLE + && mRow.mHapticPlugin != null) { + mRow.mHapticPlugin.onProgressChanged(seekBar, progress, fromUser); + if (!fromUser) { + // Consider a change from program as the volume key being continuously pressed + mRow.mHapticPlugin.onKeyDown(); + } + } if (D.BUG) Log.d(TAG, AudioSystem.streamToString(mRow.stream) + " onProgressChanged " + progress + " fromUser=" + fromUser); if (!fromUser) return; @@ -2485,6 +2531,9 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, @Override public void onStartTrackingTouch(SeekBar seekBar) { if (D.BUG) Log.d(TAG, "onStartTrackingTouch"+ " " + mRow.stream); + if (mRow.mHapticPlugin != null) { + mRow.mHapticPlugin.onStartTrackingTouch(seekBar); + } mController.setActiveStream(mRow.stream); mRow.tracking = true; } @@ -2492,6 +2541,9 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, @Override public void onStopTrackingTouch(SeekBar seekBar) { if (D.BUG) Log.d(TAG, "onStopTrackingTouch"+ " " + mRow.stream); + if (mRow.mHapticPlugin != null) { + mRow.mHapticPlugin.onStopTrackingTouch(seekBar); + } mRow.tracking = false; mRow.userAttempt = SystemClock.uptimeMillis(); final int userLevel = getImpliedLevel(seekBar, seekBar.getProgress()); @@ -2524,6 +2576,22 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, } private static class VolumeRow { + private static final SliderHapticFeedbackConfig sSliderHapticFeedbackConfig = + new SliderHapticFeedbackConfig( + /* velocityInterpolatorFactor= */ 1f, + /* progressInterpolatorFactor= */ 1f, + /* progressBasedDragMinScale= */ 0f, + /* progressBasedDragMaxScale= */ 0.2f, + /* additionalVelocityMaxBump= */ 0.15f, + /* deltaMillisForDragInterval= */ 0f, + /* deltaProgressForDragThreshold= */ 0.015f, + /* numberOfLowTicks= */ 5, + /* maxVelocityToScale= */ 300f, + /* velocityAxis= */ MotionEvent.AXIS_Y, + /* upperBookendScale= */ 1f, + /* lowerBookendScale= */ 0.05f, + /* exponent= */ 1f / 0.89f); + private View view; private TextView header; private ImageButton icon; @@ -2544,6 +2612,7 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, private ObjectAnimator anim; // slider progress animation for non-touch-related updates private int animTargetProgress; private int lastAudibleLevel = 1; + private SeekableSliderHapticPlugin mHapticPlugin; void setIcon(int iconRes, Resources.Theme theme) { if (icon != null) { @@ -2554,6 +2623,50 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, sliderProgressIcon.setDrawable(view.getResources().getDrawable(iconRes, theme)); } } + + void createPlugin( + VibratorHelper vibratorHelper, + com.android.systemui.util.time.SystemClock systemClock, + CoroutineDispatcher mainDispatcher, + CoroutineScope applicationScope) { + if (!hapticVolumeSlider() || mHapticPlugin != null) return; + + mHapticPlugin = new SeekableSliderHapticPlugin( + vibratorHelper, + systemClock, + mainDispatcher, + applicationScope, + sSliderHapticFeedbackConfig); + } + + + @SuppressLint("ClickableViewAccessibility") + void addTouchListener() { + slider.setOnTouchListener(new View.OnTouchListener() { + @Override + public boolean onTouch(View view, MotionEvent motionEvent) { + if (mHapticPlugin != null) { + mHapticPlugin.onTouchEvent(motionEvent); + } + return false; + } + }); + } + + void addHaptics() { + if (mHapticPlugin != null) { + addTouchListener(); + mHapticPlugin.start(); + } + } + + @SuppressLint("ClickableViewAccessibility") + void removeHaptics() { + slider.setOnTouchListener(null); + if (mHapticPlugin != null) { + mHapticPlugin.stop(); + } + } } /** diff --git a/packages/SystemUI/src/com/android/systemui/volume/dagger/VolumeModule.java b/packages/SystemUI/src/com/android/systemui/volume/dagger/VolumeModule.java index 497c4cb070f0..f180a942af70 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/dagger/VolumeModule.java +++ b/packages/SystemUI/src/com/android/systemui/volume/dagger/VolumeModule.java @@ -22,16 +22,20 @@ import android.os.Looper; import com.android.internal.jank.InteractionJankMonitor; import com.android.systemui.CoreStartable; +import com.android.systemui.dagger.qualifiers.Application; +import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dump.DumpManager; import com.android.systemui.media.dialog.MediaOutputDialogFactory; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.VolumeDialog; import com.android.systemui.plugins.VolumeDialogController; +import com.android.systemui.statusbar.VibratorHelper; import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.DevicePostureController; import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.util.settings.SecureSettings; +import com.android.systemui.util.time.SystemClock; import com.android.systemui.volume.CsdWarningDialog; import com.android.systemui.volume.VolumeComponent; import com.android.systemui.volume.VolumeDialogComponent; @@ -49,6 +53,9 @@ import dagger.multibindings.ClassKey; import dagger.multibindings.IntoMap; import dagger.multibindings.IntoSet; +import kotlinx.coroutines.CoroutineDispatcher; +import kotlinx.coroutines.CoroutineScope; + /** Dagger Module for code in the volume package. */ @Module( subcomponents = { @@ -90,7 +97,11 @@ public interface VolumeModule { CsdWarningDialog.Factory csdFactory, DevicePostureController devicePostureController, DumpManager dumpManager, - Lazy<SecureSettings> secureSettings) { + Lazy<SecureSettings> secureSettings, + VibratorHelper vibratorHelper, + @Main CoroutineDispatcher mainDispatcher, + @Application CoroutineScope applicationScope, + SystemClock systemClock) { VolumeDialogImpl impl = new VolumeDialogImpl( context, volumeDialogController, @@ -106,7 +117,11 @@ public interface VolumeModule { devicePostureController, Looper.getMainLooper(), dumpManager, - secureSettings); + secureSettings, + vibratorHelper, + mainDispatcher, + applicationScope, + systemClock); impl.setStreamImportant(AudioManager.STREAM_SYSTEM, false); impl.setAutomute(true); impl.setSilentMode(false); diff --git a/packages/SystemUI/src/com/android/systemui/wallet/controller/QuickAccessWalletController.java b/packages/SystemUI/src/com/android/systemui/wallet/controller/QuickAccessWalletController.java index e031be2a72dd..e0228d913977 100644 --- a/packages/SystemUI/src/com/android/systemui/wallet/controller/QuickAccessWalletController.java +++ b/packages/SystemUI/src/com/android/systemui/wallet/controller/QuickAccessWalletController.java @@ -17,10 +17,13 @@ package com.android.systemui.wallet.controller; import static com.android.systemui.wallet.controller.QuickAccessWalletController.WalletChangeEvent.DEFAULT_PAYMENT_APP_CHANGE; +import static com.android.systemui.wallet.controller.QuickAccessWalletController.WalletChangeEvent.DEFAULT_WALLET_APP_CHANGE; import static com.android.systemui.wallet.controller.QuickAccessWalletController.WalletChangeEvent.WALLET_PREFERENCE_CHANGE; import android.annotation.WorkerThread; import android.app.PendingIntent; +import android.app.role.OnRoleHoldersChangedListener; +import android.app.role.RoleManager; import android.content.Context; import android.content.Intent; import android.database.ContentObserver; @@ -31,12 +34,12 @@ import android.service.quickaccesswallet.QuickAccessWalletClient; import android.service.quickaccesswallet.QuickAccessWalletClientImpl; import android.util.Log; -import com.android.systemui.res.R; import com.android.systemui.animation.ActivityLaunchAnimator; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.plugins.ActivityStarter; +import com.android.systemui.res.R; import com.android.systemui.util.settings.SecureSettings; import com.android.systemui.util.time.SystemClock; import com.android.systemui.wallet.ui.WalletActivity; @@ -58,6 +61,7 @@ public class QuickAccessWalletController { */ public enum WalletChangeEvent { DEFAULT_PAYMENT_APP_CHANGE, + DEFAULT_WALLET_APP_CHANGE, WALLET_PREFERENCE_CHANGE, } @@ -71,9 +75,12 @@ public class QuickAccessWalletController { private QuickAccessWalletClient mQuickAccessWalletClient; private ContentObserver mWalletPreferenceObserver; + private RoleManager mRoleManager; + private OnRoleHoldersChangedListener mDefaultWalletAppObserver; private ContentObserver mDefaultPaymentAppObserver; private int mWalletPreferenceChangeEvents = 0; private int mDefaultPaymentAppChangeEvents = 0; + private int mDefaultWalletAppChangeEvents = 0; private boolean mWalletEnabled = false; private long mQawClientCreatedTimeMillis; @@ -89,6 +96,7 @@ public class QuickAccessWalletController { mExecutor = executor; mBgExecutor = bgExecutor; mSecureSettings = secureSettings; + mRoleManager = mContext.getSystemService(RoleManager.class); mQuickAccessWalletClient = quickAccessWalletClient; mClock = clock; mQawClientCreatedTimeMillis = mClock.elapsedRealtime(); @@ -122,6 +130,8 @@ public class QuickAccessWalletController { setupWalletPreferenceObserver(); } else if (event == DEFAULT_PAYMENT_APP_CHANGE) { setupDefaultPaymentAppObserver(cardsRetriever); + } else if (event == DEFAULT_WALLET_APP_CHANGE) { + setupDefaultWalletAppObserver(cardsRetriever); } } } @@ -141,6 +151,12 @@ public class QuickAccessWalletController { if (mDefaultPaymentAppChangeEvents == 0) { mSecureSettings.unregisterContentObserver(mDefaultPaymentAppObserver); } + } else if (event == DEFAULT_WALLET_APP_CHANGE && mDefaultWalletAppObserver != null) { + mDefaultWalletAppChangeEvents--; + if (mDefaultWalletAppChangeEvents == 0) { + mRoleManager.removeOnRoleHoldersChangedListenerAsUser(mDefaultWalletAppObserver, + UserHandle.ALL); + } } } } @@ -300,6 +316,25 @@ public class QuickAccessWalletController { mDefaultPaymentAppChangeEvents++; } + private void setupDefaultWalletAppObserver( + QuickAccessWalletClient.OnWalletCardsRetrievedCallback cardsRetriever) { + if (mDefaultWalletAppObserver == null) { + mDefaultWalletAppObserver = (roleName, user) -> { + if (!roleName.equals(RoleManager.ROLE_WALLET)) { + return; + } + mExecutor.execute(() -> { + reCreateWalletClient(); + updateWalletPreference(); + queryWalletCards(cardsRetriever); + }); + }; + mRoleManager.addOnRoleHoldersChangedListenerAsUser(mExecutor, + mDefaultWalletAppObserver, UserHandle.ALL); + } + mDefaultWalletAppChangeEvents++; + } + private void setupWalletPreferenceObserver() { if (mWalletPreferenceObserver == null) { mWalletPreferenceObserver = new ContentObserver(null /* handler */) { diff --git a/packages/SystemUI/src/com/android/systemui/wallet/controller/WalletContextualSuggestionsController.kt b/packages/SystemUI/src/com/android/systemui/wallet/controller/WalletContextualSuggestionsController.kt index 75df1bd2f680..eb4ff1722dcc 100644 --- a/packages/SystemUI/src/com/android/systemui/wallet/controller/WalletContextualSuggestionsController.kt +++ b/packages/SystemUI/src/com/android/systemui/wallet/controller/WalletContextualSuggestionsController.kt @@ -84,7 +84,9 @@ constructor( walletController.setupWalletChangeObservers( callback, QuickAccessWalletController.WalletChangeEvent.WALLET_PREFERENCE_CHANGE, - QuickAccessWalletController.WalletChangeEvent.DEFAULT_PAYMENT_APP_CHANGE + QuickAccessWalletController.WalletChangeEvent + .DEFAULT_PAYMENT_APP_CHANGE, + QuickAccessWalletController.WalletChangeEvent.DEFAULT_WALLET_APP_CHANGE ) walletController.updateWalletPreference() walletController.queryWalletCards(callback, MAX_CARDS) @@ -94,7 +96,9 @@ constructor( QuickAccessWalletController.WalletChangeEvent .WALLET_PREFERENCE_CHANGE, QuickAccessWalletController.WalletChangeEvent - .DEFAULT_PAYMENT_APP_CHANGE + .DEFAULT_PAYMENT_APP_CHANGE, + QuickAccessWalletController.WalletChangeEvent + .DEFAULT_WALLET_APP_CHANGE ) } } diff --git a/packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/WallpaperRepository.kt b/packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/WallpaperRepository.kt index b8f95832b852..1ba269e25dff 100644 --- a/packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/WallpaperRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/WallpaperRepository.kt @@ -24,7 +24,7 @@ import android.content.IntentFilter import android.os.UserHandle import com.android.systemui.broadcast.BroadcastDispatcher import com.android.systemui.dagger.SysUISingleton -import com.android.systemui.dagger.qualifiers.Application +import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.user.data.model.SelectedUserModel import com.android.systemui.user.data.model.SelectionStatus import com.android.systemui.user.data.repository.UserRepository @@ -54,7 +54,7 @@ interface WallpaperRepository { class WallpaperRepositoryImpl @Inject constructor( - @Application scope: CoroutineScope, + @Background scope: CoroutineScope, broadcastDispatcher: BroadcastDispatcher, userRepository: UserRepository, private val wallpaperManager: WallpaperManager, diff --git a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt index c2efc05132ba..c2efc05132ba 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt diff --git a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSimPinViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSimPinViewControllerTest.kt index 0959f1b2bcf6..0959f1b2bcf6 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSimPinViewControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSimPinViewControllerTest.kt diff --git a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSimPukViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSimPukViewControllerTest.kt index 1281e4409a83..1281e4409a83 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSimPukViewControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSimPukViewControllerTest.kt diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java index d8eb05a43e40..d06457ba86ab 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java @@ -1720,6 +1720,24 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { } @Test + public void assistantVisible_sendEventToFaceAuthInteractor() { + // WHEN the assistant is visible + mKeyguardUpdateMonitor.setAssistantVisible(true); + + // THEN send event to face auth interactor + verify(mFaceAuthInteractor).onAssistantTriggeredOnLockScreen(); + } + + @Test + public void assistantNotVisible_doesNotSendEventToFaceAuthInteractor() { + // WHEN the assistant is visible + mKeyguardUpdateMonitor.setAssistantVisible(false); + + // THEN never send event to face auth interactor + verify(mFaceAuthInteractor, never()).onAssistantTriggeredOnLockScreen(); + } + + @Test public void fingerprintFailure_requestActiveUnlock_dismissKeyguard() { // GIVEN shouldTriggerActiveUnlock bouncerFullyVisible(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerTest.java index 5e5273b779c6..bc9a0a5484ac 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayerTest.java @@ -181,16 +181,16 @@ public class MenuViewLayerTest extends SysuiTestCase { @Test public void onAttachedToWindow_menuIsVisible() { mMenuViewLayer.onAttachedToWindow(); - final View menuView = mMenuViewLayer.getChildAt(LayerIndex.MENU_VIEW); + final View menuView = mMenuViewLayer.getChildAt(LayerIndex.MENU_VIEW); assertThat(menuView.getVisibility()).isEqualTo(VISIBLE); } @Test - public void onAttachedToWindow_menuIsGone() { + public void onDetachedFromWindow_menuIsGone() { mMenuViewLayer.onDetachedFromWindow(); - final View menuView = mMenuViewLayer.getChildAt(LayerIndex.MENU_VIEW); + final View menuView = mMenuViewLayer.getChildAt(LayerIndex.MENU_VIEW); assertThat(menuView.getVisibility()).isEqualTo(GONE); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyboard/stickykeys/ui/StickyKeysIndicatorCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyboard/stickykeys/ui/StickyKeysIndicatorCoordinatorTest.kt new file mode 100644 index 000000000000..df73cc8f0212 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/keyboard/stickykeys/ui/StickyKeysIndicatorCoordinatorTest.kt @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.keyboard.stickykeys.ui + +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.compose.ComposeFacade +import com.android.systemui.keyboard.data.repository.FakeStickyKeysRepository +import com.android.systemui.keyboard.data.repository.keyboardRepository +import com.android.systemui.keyboard.stickykeys.StickyKeysLogger +import com.android.systemui.keyboard.stickykeys.shared.model.Locked +import com.android.systemui.keyboard.stickykeys.shared.model.ModifierKey.SHIFT +import com.android.systemui.keyboard.stickykeys.ui.viewmodel.StickyKeysIndicatorViewModel +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.statusbar.phone.ComponentSystemUIDialog +import com.android.systemui.statusbar.phone.SystemUIDialogFactory +import com.android.systemui.util.mockito.any +import com.android.systemui.util.mockito.mock +import com.android.systemui.util.mockito.whenever +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.StandardTestDispatcher +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.runCurrent +import org.junit.Assume +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 +import org.mockito.Mockito.anyBoolean +import org.mockito.Mockito.anyInt +import org.mockito.Mockito.verify +import org.mockito.Mockito.verifyZeroInteractions + +@OptIn(ExperimentalCoroutinesApi::class) +@SmallTest +@RunWith(JUnit4::class) +class StickyKeysIndicatorCoordinatorTest : SysuiTestCase() { + + private lateinit var coordinator: StickyKeysIndicatorCoordinator + private val testScope = TestScope(StandardTestDispatcher()) + private val stickyKeysRepository = FakeStickyKeysRepository() + private val dialog = mock<ComponentSystemUIDialog>() + + @Before + fun setup() { + Assume.assumeTrue(ComposeFacade.isComposeAvailable()) + val dialogFactory = mock<SystemUIDialogFactory> { + whenever(applicationContext).thenReturn(context) + whenever(create(any(), anyInt(), anyBoolean())).thenReturn(dialog) + } + val keyboardRepository = Kosmos().keyboardRepository + val viewModel = StickyKeysIndicatorViewModel( + stickyKeysRepository, + keyboardRepository, + testScope.backgroundScope) + coordinator = StickyKeysIndicatorCoordinator( + testScope.backgroundScope, + dialogFactory, + viewModel, + mock<StickyKeysLogger>()) + coordinator.startListening() + keyboardRepository.setIsAnyKeyboardConnected(true) + } + + @Test + fun dialogIsShownWhenStickyKeysAreEmitted() { + testScope.run { + verifyZeroInteractions(dialog) + + stickyKeysRepository.setStickyKeys(linkedMapOf(SHIFT to Locked(true))) + runCurrent() + + verify(dialog).show() + } + } + + @Test + fun dialogDisappearsWhenStickyKeysAreEmpty() { + testScope.run { + verifyZeroInteractions(dialog) + + stickyKeysRepository.setStickyKeys(linkedMapOf(SHIFT to Locked(true))) + runCurrent() + stickyKeysRepository.setStickyKeys(linkedMapOf()) + runCurrent() + + verify(dialog).dismiss() + } + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyboard/stickykeys/ui/viewmodel/StickyKeysIndicatorViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyboard/stickykeys/ui/viewmodel/StickyKeysIndicatorViewModelTest.kt index d397fc202637..8a713688acf9 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyboard/stickykeys/ui/viewmodel/StickyKeysIndicatorViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyboard/stickykeys/ui/viewmodel/StickyKeysIndicatorViewModelTest.kt @@ -34,6 +34,7 @@ import com.android.systemui.keyboard.stickykeys.shared.model.ModifierKey.SHIFT import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.mock import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runCurrent @@ -46,6 +47,7 @@ import org.mockito.ArgumentCaptor import org.mockito.Mockito.verify import org.mockito.Mockito.verifyZeroInteractions +@OptIn(ExperimentalCoroutinesApi::class) @SmallTest @RunWith(JUnit4::class) class StickyKeysIndicatorViewModelTest : SysuiTestCase() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java index b57cf53911e9..8a3a4342915b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java @@ -97,6 +97,7 @@ import com.android.systemui.flags.Flags; import com.android.systemui.flags.SystemPropertiesHelper; import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor; import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel; +import com.android.systemui.kosmos.KosmosJavaAdapter; import com.android.systemui.log.SessionTracker; import com.android.systemui.navigationbar.NavigationModeController; import com.android.systemui.scene.FakeWindowRootViewComponent; @@ -150,6 +151,7 @@ import kotlinx.coroutines.test.TestScope; @TestableLooper.RunWithLooper @SmallTest public class KeyguardViewMediatorTest extends SysuiTestCase { + private final KosmosJavaAdapter mKosmos = new KosmosJavaAdapter(this); private KeyguardViewMediator mViewMediator; private final TestScope mTestScope = TestScopeProvider.getTestScope(); @@ -265,7 +267,8 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { mShadeWindowLogger, () -> mSelectedUserInteractor, mUserTracker, - mSceneContainerFlags); + mSceneContainerFlags, + mKosmos::getCommunalInteractor); mFeatureFlags = new FakeFeatureFlags(); mFeatureFlags.set(Flags.KEYGUARD_WM_STATE_REFACTOR, false); mSetFlagsRule.enableFlags(FLAG_REFACTOR_GET_CURRENT_USER); @@ -306,6 +309,28 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { @Test @TestableLooper.RunWithLooper(setAsMainLooper = true) + public void testRaceCondition_doNotRegisterCentralSurfacesImmediately() { + create(false); + + // GIVEN central surfaces is not registered with KeyguardViewMediator, but a call to enable + // keyguard comes in + mViewMediator.onSystemReady(); + mViewMediator.setKeyguardEnabled(true); + TestableLooper.get(this).processAllMessages(); + + // If this step has been reached, then system ui has not crashed. Now register + // CentralSurfaces + assertFalse(mViewMediator.isShowingAndNotOccluded()); + register(); + TestableLooper.get(this).moveTimeForward(100); + TestableLooper.get(this).processAllMessages(); + + // THEN keyguard is shown + assertTrue(mViewMediator.isShowingAndNotOccluded()); + } + + @Test + @TestableLooper.RunWithLooper(setAsMainLooper = true) public void onLockdown_showKeyguard_evenIfKeyguardIsNotEnabledExternally() { // GIVEN keyguard is not enabled and isn't showing mViewMediator.onSystemReady(); @@ -1136,6 +1161,11 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { } private void createAndStartViewMediator(boolean orderUnlockAndWake) { + create(orderUnlockAndWake); + register(); + } + + private void create(boolean orderUnlockAndWake) { mContext.getOrCreateTestableResources().addOverride( com.android.internal.R.bool.config_orderUnlockAndWake, orderUnlockAndWake); @@ -1186,7 +1216,9 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { mSelectedUserInteractor, mKeyguardInteractor); mViewMediator.start(); + } + private void register() { mViewMediator.registerCentralSurfaces(mCentralSurfaces, null, null, null, null, null); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractorTest.kt index 809947d2fec7..6092b6b351af 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractorTest.kt @@ -66,6 +66,7 @@ class FromPrimaryBouncerTransitionInteractorTest : KeyguardTransitionInteractorT bgDispatcher = super.testDispatcher, mainDispatcher = super.testDispatcher, keyguardInteractor = super.keyguardInteractor, + communalInteractor = super.communalInteractor, flags = FakeFeatureFlags(), keyguardSecurityModel = mock(), powerInteractor = PowerInteractorFactory.create().powerInteractor, diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTestCase.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTestCase.kt index 339fd22259db..a03aed04432b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTestCase.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTestCase.kt @@ -17,14 +17,18 @@ package com.android.systemui.keyguard.domain.interactor import com.android.systemui.SysuiTestCase +import com.android.systemui.communal.domain.interactor.CommunalInteractor +import com.android.systemui.communal.domain.interactor.communalInteractor import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository +import com.android.systemui.testKosmos import com.android.systemui.util.mockito.mock import dagger.Lazy import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.TestScope open class KeyguardTransitionInteractorTestCase : SysuiTestCase() { + private val kosmos = testKosmos() val testDispatcher = StandardTestDispatcher() var testScope = TestScope(testDispatcher) @@ -32,6 +36,7 @@ open class KeyguardTransitionInteractorTestCase : SysuiTestCase() { lateinit var transitionRepository: FakeKeyguardTransitionRepository lateinit var keyguardInteractor: KeyguardInteractor + lateinit var communalInteractor: CommunalInteractor lateinit var transitionInteractor: KeyguardTransitionInteractor /** @@ -51,6 +56,8 @@ open class KeyguardTransitionInteractorTestCase : SysuiTestCase() { keyguardInteractor = KeyguardInteractorFactory.create(repository = keyguardRepository).keyguardInteractor + communalInteractor = kosmos.communalInteractor + transitionInteractor = KeyguardTransitionInteractorFactory.create( repository = transitionRepository, diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt index 8b6611f339c0..892be354180a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt @@ -23,8 +23,9 @@ import com.android.keyguard.KeyguardSecurityModel.SecurityMode.PIN import com.android.systemui.Flags.FLAG_COMMUNAL_HUB import com.android.systemui.SysuiTestCase import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository +import com.android.systemui.bouncer.data.repository.fakeKeyguardBouncerRepository import com.android.systemui.communal.domain.interactor.CommunalInteractor -import com.android.systemui.communal.domain.interactor.CommunalInteractorFactory +import com.android.systemui.communal.domain.interactor.communalInteractor import com.android.systemui.communal.shared.model.CommunalSceneKey import com.android.systemui.communal.shared.model.ObservableCommunalTransitionState import com.android.systemui.flags.FakeFeatureFlags @@ -34,6 +35,8 @@ import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository import com.android.systemui.keyguard.data.repository.FakeKeyguardSurfaceBehindRepository import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository import com.android.systemui.keyguard.data.repository.InWindowLauncherUnlockAnimationRepository +import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository +import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository import com.android.systemui.keyguard.shared.model.BiometricUnlockModel import com.android.systemui.keyguard.shared.model.DozeStateModel import com.android.systemui.keyguard.shared.model.DozeTransitionModel @@ -42,11 +45,15 @@ import com.android.systemui.keyguard.shared.model.StatusBarState import com.android.systemui.keyguard.shared.model.TransitionInfo import com.android.systemui.keyguard.shared.model.TransitionState import com.android.systemui.keyguard.shared.model.TransitionStep +import com.android.systemui.kosmos.testDispatcher +import com.android.systemui.kosmos.testScope import com.android.systemui.power.domain.interactor.PowerInteractor import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAsleepForTest import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAwakeForTest import com.android.systemui.power.domain.interactor.PowerInteractorFactory import com.android.systemui.shade.data.repository.FakeShadeRepository +import com.android.systemui.shade.data.repository.fakeShadeRepository +import com.android.systemui.testKosmos import com.android.systemui.user.domain.interactor.SelectedUserInteractor import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.mock @@ -57,7 +64,6 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.cancelChildren import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.flowOf -import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.advanceUntilIdle import kotlinx.coroutines.test.runCurrent @@ -83,7 +89,8 @@ import org.mockito.MockitoAnnotations @SmallTest @RunWith(JUnit4::class) class KeyguardTransitionScenariosTest : SysuiTestCase() { - private lateinit var testScope: TestScope + private val kosmos = testKosmos() + private val testScope = kosmos.testScope private lateinit var keyguardRepository: FakeKeyguardRepository private lateinit var bouncerRepository: FakeKeyguardBouncerRepository @@ -119,17 +126,14 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { @Before fun setUp() { MockitoAnnotations.initMocks(this) - val testDispatcher = StandardTestDispatcher() - testScope = TestScope(testDispatcher) - keyguardRepository = FakeKeyguardRepository() - bouncerRepository = FakeKeyguardBouncerRepository() + keyguardRepository = kosmos.fakeKeyguardRepository + bouncerRepository = kosmos.fakeKeyguardBouncerRepository commandQueue = FakeCommandQueue() - shadeRepository = FakeShadeRepository() - transitionRepository = spy(FakeKeyguardTransitionRepository()) + shadeRepository = kosmos.fakeShadeRepository + transitionRepository = spy(kosmos.fakeKeyguardTransitionRepository) powerInteractor = PowerInteractorFactory.create().powerInteractor - communalInteractor = - CommunalInteractorFactory.create(testScope = testScope).communalInteractor + communalInteractor = kosmos.communalInteractor whenever(keyguardSecurityModel.getSecurityMode(anyInt())).thenReturn(PIN) @@ -152,16 +156,17 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { val glanceableHubTransitions = GlanceableHubTransitions( - testScope, - transitionInteractor, - transitionRepository, - communalInteractor + scope = testScope, + bgDispatcher = kosmos.testDispatcher, + transitionInteractor = transitionInteractor, + transitionRepository = transitionRepository, + communalInteractor = communalInteractor ) fromLockscreenTransitionInteractor = FromLockscreenTransitionInteractor( scope = testScope, - bgDispatcher = testDispatcher, - mainDispatcher = testDispatcher, + bgDispatcher = kosmos.testDispatcher, + mainDispatcher = kosmos.testDispatcher, keyguardInteractor = keyguardInteractor, transitionRepository = transitionRepository, transitionInteractor = transitionInteractor, @@ -184,14 +189,15 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { fromPrimaryBouncerTransitionInteractor = FromPrimaryBouncerTransitionInteractor( scope = testScope, - bgDispatcher = testDispatcher, - mainDispatcher = testDispatcher, + bgDispatcher = kosmos.testDispatcher, + mainDispatcher = kosmos.testDispatcher, keyguardInteractor = keyguardInteractor, transitionRepository = transitionRepository, transitionInteractor = transitionInteractor, flags = featureFlags, keyguardSecurityModel = keyguardSecurityModel, powerInteractor = powerInteractor, + communalInteractor = communalInteractor, selectedUserInteractor = mSelectedUserInteractor, ) .apply { start() } @@ -199,8 +205,8 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { fromDreamingTransitionInteractor = FromDreamingTransitionInteractor( scope = testScope, - bgDispatcher = testDispatcher, - mainDispatcher = testDispatcher, + bgDispatcher = kosmos.testDispatcher, + mainDispatcher = kosmos.testDispatcher, keyguardInteractor = keyguardInteractor, transitionRepository = transitionRepository, transitionInteractor = transitionInteractor, @@ -210,8 +216,8 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { fromDreamingLockscreenHostedTransitionInteractor = FromDreamingLockscreenHostedTransitionInteractor( scope = testScope, - bgDispatcher = testDispatcher, - mainDispatcher = testDispatcher, + bgDispatcher = kosmos.testDispatcher, + mainDispatcher = kosmos.testDispatcher, keyguardInteractor = keyguardInteractor, transitionRepository = transitionRepository, transitionInteractor = transitionInteractor, @@ -221,8 +227,8 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { fromAodTransitionInteractor = FromAodTransitionInteractor( scope = testScope, - bgDispatcher = testDispatcher, - mainDispatcher = testDispatcher, + bgDispatcher = kosmos.testDispatcher, + mainDispatcher = kosmos.testDispatcher, keyguardInteractor = keyguardInteractor, transitionRepository = transitionRepository, transitionInteractor = transitionInteractor, @@ -232,8 +238,8 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { fromGoneTransitionInteractor = FromGoneTransitionInteractor( scope = testScope, - bgDispatcher = testDispatcher, - mainDispatcher = testDispatcher, + bgDispatcher = kosmos.testDispatcher, + mainDispatcher = kosmos.testDispatcher, keyguardInteractor = keyguardInteractor, transitionRepository = transitionRepository, transitionInteractor = transitionInteractor, @@ -244,20 +250,21 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { fromDozingTransitionInteractor = FromDozingTransitionInteractor( scope = testScope, - bgDispatcher = testDispatcher, - mainDispatcher = testDispatcher, + bgDispatcher = kosmos.testDispatcher, + mainDispatcher = kosmos.testDispatcher, keyguardInteractor = keyguardInteractor, transitionRepository = transitionRepository, transitionInteractor = transitionInteractor, powerInteractor = powerInteractor, + communalInteractor = communalInteractor, ) .apply { start() } fromOccludedTransitionInteractor = FromOccludedTransitionInteractor( scope = testScope, - bgDispatcher = testDispatcher, - mainDispatcher = testDispatcher, + bgDispatcher = kosmos.testDispatcher, + mainDispatcher = kosmos.testDispatcher, keyguardInteractor = keyguardInteractor, transitionRepository = transitionRepository, transitionInteractor = transitionInteractor, @@ -268,22 +275,26 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { fromAlternateBouncerTransitionInteractor = FromAlternateBouncerTransitionInteractor( scope = testScope, - bgDispatcher = testDispatcher, - mainDispatcher = testDispatcher, + bgDispatcher = kosmos.testDispatcher, + mainDispatcher = kosmos.testDispatcher, keyguardInteractor = keyguardInteractor, transitionRepository = transitionRepository, transitionInteractor = transitionInteractor, + communalInteractor = communalInteractor, powerInteractor = powerInteractor, ) .apply { start() } fromGlanceableHubTransitionInteractor = FromGlanceableHubTransitionInteractor( - bgDispatcher = testDispatcher, - mainDispatcher = testDispatcher, + scope = testScope, + bgDispatcher = kosmos.testDispatcher, + mainDispatcher = kosmos.testDispatcher, glanceableHubTransitions = glanceableHubTransitions, + keyguardInteractor = keyguardInteractor, transitionRepository = transitionRepository, transitionInteractor = transitionInteractor, + powerInteractor = powerInteractor, ) .apply { start() } } @@ -725,6 +736,38 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { } @Test + fun dozingToGlanceableHub() = + testScope.runTest { + // GIVEN a prior transition has run to DOZING + runTransitionAndSetWakefulness(KeyguardState.GLANCEABLE_HUB, KeyguardState.DOZING) + runCurrent() + + // GIVEN the device is idle on the glanceable hub + val idleTransitionState = + MutableStateFlow<ObservableCommunalTransitionState>( + ObservableCommunalTransitionState.Idle(CommunalSceneKey.Communal) + ) + communalInteractor.setTransitionState(idleTransitionState) + runCurrent() + + // WHEN the device begins to wake + powerInteractor.setAwakeForTest() + runCurrent() + + val info = + withArgCaptor<TransitionInfo> { + verify(transitionRepository).startTransition(capture()) + } + // THEN a transition to DOZING should occur + assertThat(info.ownerName).isEqualTo(FromDozingTransitionInteractor::class.simpleName) + assertThat(info.from).isEqualTo(KeyguardState.DOZING) + assertThat(info.to).isEqualTo(KeyguardState.GLANCEABLE_HUB) + assertThat(info.animator).isNotNull() + + coroutineContext.cancelChildren() + } + + @Test fun goneToDozing() = testScope.runTest { // GIVEN a device with AOD not available @@ -984,6 +1027,45 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { } @Test + fun alternateBouncerToGlanceableHub() = + testScope.runTest { + // GIVEN a prior transition has run to ALTERNATE_BOUNCER + bouncerRepository.setAlternateVisible(true) + runTransitionAndSetWakefulness( + KeyguardState.LOCKSCREEN, + KeyguardState.ALTERNATE_BOUNCER + ) + + // GIVEN the primary bouncer isn't showing and device not sleeping + bouncerRepository.setPrimaryShow(false) + + // GIVEN the device is idle on the glanceable hub + val idleTransitionState = + MutableStateFlow<ObservableCommunalTransitionState>( + ObservableCommunalTransitionState.Idle(CommunalSceneKey.Communal) + ) + communalInteractor.setTransitionState(idleTransitionState) + runCurrent() + + // WHEN the alternateBouncer stops showing + bouncerRepository.setAlternateVisible(false) + advanceUntilIdle() + + val info = + withArgCaptor<TransitionInfo> { + verify(transitionRepository).startTransition(capture()) + } + // THEN a transition to LOCKSCREEN should occur + assertThat(info.ownerName) + .isEqualTo(FromAlternateBouncerTransitionInteractor::class.simpleName) + assertThat(info.from).isEqualTo(KeyguardState.ALTERNATE_BOUNCER) + assertThat(info.to).isEqualTo(KeyguardState.GLANCEABLE_HUB) + assertThat(info.animator).isNotNull() + + coroutineContext.cancelChildren() + } + + @Test fun primaryBouncerToAod() = testScope.runTest { // GIVEN a prior transition has run to PRIMARY_BOUNCER @@ -1046,7 +1128,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { bouncerRepository.setPrimaryShow(true) runTransitionAndSetWakefulness(KeyguardState.LOCKSCREEN, KeyguardState.PRIMARY_BOUNCER) - // WHEN the alternateBouncer stops showing + // WHEN the primaryBouncer stops showing bouncerRepository.setPrimaryShow(false) runCurrent() @@ -1064,6 +1146,39 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { } @Test + fun primaryBouncerToGlanceableHub() = + testScope.runTest { + // GIVEN a prior transition has run to PRIMARY_BOUNCER + bouncerRepository.setPrimaryShow(true) + runTransitionAndSetWakefulness(KeyguardState.LOCKSCREEN, KeyguardState.PRIMARY_BOUNCER) + + // GIVEN the device is idle on the glanceable hub + val idleTransitionState = + MutableStateFlow<ObservableCommunalTransitionState>( + ObservableCommunalTransitionState.Idle(CommunalSceneKey.Communal) + ) + communalInteractor.setTransitionState(idleTransitionState) + runCurrent() + + // WHEN the primaryBouncer stops showing + bouncerRepository.setPrimaryShow(false) + runCurrent() + + val info = + withArgCaptor<TransitionInfo> { + verify(transitionRepository).startTransition(capture()) + } + // THEN a transition to LOCKSCREEN should occur + assertThat(info.ownerName) + .isEqualTo(FromPrimaryBouncerTransitionInteractor::class.simpleName) + assertThat(info.from).isEqualTo(KeyguardState.PRIMARY_BOUNCER) + assertThat(info.to).isEqualTo(KeyguardState.GLANCEABLE_HUB) + assertThat(info.animator).isNotNull() + + coroutineContext.cancelChildren() + } + + @Test fun primaryBouncerToDreamingLockscreenHosted() = testScope.runTest { // GIVEN device dreaming with the lockscreen hosted dream and not dozing @@ -1577,6 +1692,78 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() { coroutineContext.cancelChildren() } + @Test + fun glanceableHubToDozing() = + testScope.runTest { + // GIVEN a prior transition has run to GLANCEABLE_HUB + runTransitionAndSetWakefulness(KeyguardState.LOCKSCREEN, KeyguardState.GLANCEABLE_HUB) + + // WHEN the device begins to sleep + powerInteractor.setAsleepForTest() + runCurrent() + + val info = + withArgCaptor<TransitionInfo> { + verify(transitionRepository).startTransition(capture()) + } + // THEN a transition to DOZING should occur + assertThat(info.ownerName) + .isEqualTo(FromGlanceableHubTransitionInteractor::class.simpleName) + assertThat(info.from).isEqualTo(KeyguardState.GLANCEABLE_HUB) + assertThat(info.to).isEqualTo(KeyguardState.DOZING) + assertThat(info.animator).isNotNull() + + coroutineContext.cancelChildren() + } + + @Test + fun glanceableHubToPrimaryBouncer() = + testScope.runTest { + // GIVEN a prior transition has run to ALTERNATE_BOUNCER + runTransitionAndSetWakefulness(KeyguardState.LOCKSCREEN, KeyguardState.GLANCEABLE_HUB) + + // WHEN the primary bouncer shows + bouncerRepository.setPrimaryShow(true) + runCurrent() + + val info = + withArgCaptor<TransitionInfo> { + verify(transitionRepository).startTransition(capture()) + } + // THEN a transition to PRIMARY_BOUNCER should occur + assertThat(info.ownerName) + .isEqualTo(FromGlanceableHubTransitionInteractor::class.simpleName) + assertThat(info.from).isEqualTo(KeyguardState.GLANCEABLE_HUB) + assertThat(info.to).isEqualTo(KeyguardState.PRIMARY_BOUNCER) + assertThat(info.animator).isNotNull() + + coroutineContext.cancelChildren() + } + + @Test + fun glanceableHubToAlternateBouncer() = + testScope.runTest { + // GIVEN a prior transition has run to ALTERNATE_BOUNCER + runTransitionAndSetWakefulness(KeyguardState.LOCKSCREEN, KeyguardState.GLANCEABLE_HUB) + + // WHEN the primary bouncer shows + bouncerRepository.setAlternateVisible(true) + runCurrent() + + val info = + withArgCaptor<TransitionInfo> { + verify(transitionRepository).startTransition(capture()) + } + // THEN a transition to PRIMARY_BOUNCER should occur + assertThat(info.ownerName) + .isEqualTo(FromGlanceableHubTransitionInteractor::class.simpleName) + assertThat(info.from).isEqualTo(KeyguardState.GLANCEABLE_HUB) + assertThat(info.to).isEqualTo(KeyguardState.ALTERNATE_BOUNCER) + assertThat(info.animator).isNotNull() + + coroutineContext.cancelChildren() + } + private fun createKeyguardInteractor(): KeyguardInteractor { return KeyguardInteractorFactory.create( featureFlags = featureFlags, diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaHierarchyManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaHierarchyManagerTest.kt index 6be92756ba8a..ba7927d6b8bd 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaHierarchyManagerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaHierarchyManagerTest.kt @@ -25,8 +25,7 @@ import android.widget.FrameLayout import androidx.test.filters.SmallTest import com.android.keyguard.KeyguardViewController import com.android.systemui.SysuiTestCase -import com.android.systemui.communal.data.repository.FakeCommunalRepository -import com.android.systemui.communal.domain.interactor.CommunalInteractorFactory +import com.android.systemui.communal.domain.interactor.communalInteractor import com.android.systemui.communal.shared.model.CommunalSceneKey import com.android.systemui.controls.controller.ControlsControllerImplTest.Companion.eq import com.android.systemui.dreams.DreamOverlayStateController @@ -43,6 +42,7 @@ import com.android.systemui.statusbar.phone.KeyguardBypassController import com.android.systemui.statusbar.policy.FakeConfigurationController import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.statusbar.policy.ResourcesSplitShadeStateController +import com.android.systemui.testKosmos import com.android.systemui.util.animation.UniqueObjectHostView import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.mock @@ -79,6 +79,8 @@ import org.mockito.junit.MockitoJUnit @TestableLooper.RunWithLooper(setAsMainLooper = true) class MediaHierarchyManagerTest : SysuiTestCase() { + private val kosmos = testKosmos() + @Mock private lateinit var lockHost: MediaHost @Mock private lateinit var qsHost: MediaHost @Mock private lateinit var qqsHost: MediaHost @@ -110,10 +112,7 @@ class MediaHierarchyManagerTest : SysuiTestCase() { private lateinit var isQsBypassingShade: MutableStateFlow<Boolean> private lateinit var mediaFrame: ViewGroup private val configurationController = FakeConfigurationController() - private val communalRepository = - FakeCommunalRepository(applicationScope = testScope.backgroundScope) - private val communalInteractor = - CommunalInteractorFactory.create(communalRepository = communalRepository).communalInteractor + private val communalInteractor = kosmos.communalInteractor private val settings = FakeSettings() private lateinit var testableLooper: TestableLooper private lateinit var fakeHandler: FakeHandler diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaViewControllerTest.kt index 0a464e6047d3..b701d7f315bc 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaViewControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaViewControllerTest.kt @@ -21,6 +21,7 @@ import android.content.res.Configuration.ORIENTATION_LANDSCAPE import android.testing.AndroidTestingRunner import android.testing.TestableLooper import android.view.View +import androidx.constraintlayout.widget.ConstraintSet import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.media.controls.models.player.MediaViewHolder @@ -171,6 +172,38 @@ class MediaViewControllerTest : SysuiTestCase() { } @Test + fun testObtainViewState_expandedMatchesParentHeight() { + mediaViewController.attach(player, MediaViewController.TYPE.PLAYER) + player.measureState = + TransitionViewState().apply { + this.height = 100 + this.measureHeight = 100 + } + mediaHostStateHolder.expandedMatchesParentHeight = true + mediaHostStateHolder.expansion = 1f + mediaHostStateHolder.measurementInput = + MeasurementInput( + View.MeasureSpec.makeMeasureSpec(100, View.MeasureSpec.EXACTLY), + View.MeasureSpec.makeMeasureSpec(100, View.MeasureSpec.EXACTLY), + ) + + // Assign the height of each expanded layout + MediaViewHolder.backgroundIds.forEach { id -> + mediaViewController.expandedLayout.getConstraint(id).layout.mHeight = 100 + } + + mediaViewController.obtainViewState(mediaHostStateHolder) + + // Verify height of each expanded layout is updated to match constraint + MediaViewHolder.backgroundIds.forEach { id -> + assertTrue( + mediaViewController.expandedLayout.getConstraint(id).layout.mHeight == + ConstraintSet.MATCH_CONSTRAINT + ) + } + } + + @Test fun testSquishViewState_applySquishFraction_toTransitionViewState_alpha_forMediaPlayer() { whenever(mockViewState.copy()).thenReturn(mockCopiedState) whenever(mockCopiedState.widgetStates) diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java index 72847a6b6c45..c6cfabc61300 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java @@ -414,6 +414,18 @@ public class MediaOutputControllerTest extends SysuiTestCase { @Test public void onDeviceListUpdate_verifyDeviceListCallback() { + // This test relies on mMediaOutputController.start being called while the selected device + // list has exactly one item, and that item's id is: + // - Different from both ids in mMediaDevices. + // - Different from the id of the route published by the device under test (usually the + // built-in speakers). + // So mock the selected device to respect these two preconditions. + MediaDevice mockSelectedMediaDevice = Mockito.mock(MediaDevice.class); + when(mockSelectedMediaDevice.getId()).thenReturn(TEST_DEVICE_3_ID); + doReturn(List.of(mockSelectedMediaDevice)) + .when(mLocalMediaManager) + .getSelectedMediaDevice(); + mMediaOutputController.start(mCb); reset(mCb); @@ -434,6 +446,18 @@ public class MediaOutputControllerTest extends SysuiTestCase { @Test public void advanced_onDeviceListUpdateWithConnectedDeviceRemote_verifyItemSize() { + // This test relies on mMediaOutputController.start being called while the selected device + // list has exactly one item, and that item's id is: + // - Different from both ids in mMediaDevices. + // - Different from the id of the route published by the device under test (usually the + // built-in speakers). + // So mock the selected device to respect these two preconditions. + MediaDevice mockSelectedMediaDevice = Mockito.mock(MediaDevice.class); + when(mockSelectedMediaDevice.getId()).thenReturn(TEST_DEVICE_3_ID); + doReturn(List.of(mockSelectedMediaDevice)) + .when(mLocalMediaManager) + .getSelectedMediaDevice(); + when(mMediaDevice1.getFeatures()).thenReturn( ImmutableList.of(MediaRoute2Info.FEATURE_REMOTE_PLAYBACK)); when(mLocalMediaManager.getCurrentConnectedDevice()).thenReturn(mMediaDevice1); diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSImplTest.java index c8c134a9474a..563a3fe9fc7f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSImplTest.java @@ -35,6 +35,7 @@ import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; import android.annotation.Nullable; @@ -47,6 +48,7 @@ import android.view.Display; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.FrameLayout; import androidx.lifecycle.Lifecycle; import androidx.test.filters.SmallTest; @@ -63,6 +65,7 @@ import com.android.systemui.qs.footer.ui.binder.FooterActionsViewBinder; import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.res.R; +import com.android.systemui.scene.shared.flag.SceneContainerFlags; import com.android.systemui.settings.FakeDisplayTracker; import com.android.systemui.shade.transition.LargeScreenShadeInterpolator; import com.android.systemui.statusbar.CommandQueue; @@ -111,7 +114,8 @@ public class QSImplTest extends SysuiTestCase { @Mock private FooterActionsViewBinder mFooterActionsViewBinder; @Mock private LargeScreenShadeInterpolator mLargeScreenShadeInterpolator; @Mock private FeatureFlagsClassic mFeatureFlags; - private View mQsView; + @Mock private SceneContainerFlags mSceneContainerFlags; + private ViewGroup mQsView; private final CommandQueue mCommandQueue = new CommandQueue(mContext, new FakeDisplayTracker(mContext)); @@ -121,6 +125,9 @@ public class QSImplTest extends SysuiTestCase { @Before public void setup() { + MockitoAnnotations.initMocks(this); + when(mSceneContainerFlags.isEnabled()).thenReturn(false); + mUnderTest = instantiate(); mUnderTest.onComponentCreated(mQsComponent, null); @@ -487,9 +494,24 @@ public class QSImplTest extends SysuiTestCase { verify(mQSAnimator).setOnKeyguard(true); } - private QSImpl instantiate() { - MockitoAnnotations.initMocks(this); + @Test + public void testSceneContainerFlagsEnabled_FooterActionsRemoved_controllerNotStarted() { + when(mSceneContainerFlags.isEnabled()).thenReturn(true); + clearInvocations( + mFooterActionsViewBinder, mFooterActionsViewModel, mFooterActionsViewModelFactory); + QSImpl other = instantiate(); + + other.onComponentCreated(mQsComponent, null); + assertThat((View) other.getView().findViewById(R.id.qs_footer_actions)).isNull(); + verifyZeroInteractions( + mFooterActionsViewModel, + mFooterActionsViewBinder, + mFooterActionsViewModelFactory + ); + } + + private QSImpl instantiate() { setupQsComponent(); setUpViews(); setUpInflater(); @@ -514,7 +536,8 @@ public class QSImplTest extends SysuiTestCase { mFooterActionsViewModelFactory, mFooterActionsViewBinder, mLargeScreenShadeInterpolator, - mFeatureFlags); + mFeatureFlags, + mSceneContainerFlags); } private void setUpOther() { @@ -533,14 +556,23 @@ public class QSImplTest extends SysuiTestCase { } private void setUpViews() { - mQsView = spy(new View(mContext)); + mQsView = spy(new FrameLayout(mContext)); when(mQsComponent.getRootView()).thenReturn(mQsView); - when(mQsView.findViewById(R.id.expanded_qs_scroll_view)) + + when(mQSPanelScrollView.findViewById(R.id.expanded_qs_scroll_view)) .thenReturn(mQSPanelScrollView); - when(mQsView.findViewById(R.id.header)).thenReturn(mHeader); - when(mQsView.findViewById(android.R.id.edit)).thenReturn(new View(mContext)); - when(mQsView.findViewById(R.id.qs_footer_actions)).thenAnswer( - invocation -> new FooterActionsViewBinder().create(mContext)); + mQsView.addView(mQSPanelScrollView); + + when(mHeader.findViewById(R.id.header)).thenReturn(mHeader); + mQsView.addView(mHeader); + + View customizer = new View(mContext); + customizer.setId(android.R.id.edit); + mQsView.addView(customizer); + + View footerActionsView = new FooterActionsViewBinder().create(mContext); + footerActionsView.setId(R.id.qs_footer_actions); + mQsView.addView(footerActionsView); } private void setUpInflater() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/GlanceableHubContainerControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/GlanceableHubContainerControllerTest.kt index b7a9ea751438..45f68694e378 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/GlanceableHubContainerControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/GlanceableHubContainerControllerTest.kt @@ -25,14 +25,16 @@ import android.view.View import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.communal.data.repository.FakeCommunalRepository +import com.android.systemui.communal.data.repository.fakeCommunalRepository import com.android.systemui.communal.domain.interactor.CommunalInteractor -import com.android.systemui.communal.domain.interactor.CommunalInteractorFactory +import com.android.systemui.communal.domain.interactor.communalInteractor import com.android.systemui.communal.shared.model.CommunalSceneKey import com.android.systemui.communal.ui.viewmodel.CommunalViewModel import com.android.systemui.compose.ComposeFacade import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor import com.android.systemui.res.R import com.android.systemui.shade.domain.interactor.ShadeInteractor +import com.android.systemui.testKosmos import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat @@ -52,6 +54,8 @@ import org.mockito.MockitoAnnotations @TestableLooper.RunWithLooper(setAsMainLooper = true) @SmallTest class GlanceableHubContainerControllerTest : SysuiTestCase() { + private val kosmos = testKosmos() + @Mock private lateinit var communalViewModel: CommunalViewModel @Mock private lateinit var keyguardTransitionInteractor: KeyguardTransitionInteractor @Mock private lateinit var shadeInteractor: ShadeInteractor @@ -71,9 +75,8 @@ class GlanceableHubContainerControllerTest : SysuiTestCase() { fun setUp() { MockitoAnnotations.initMocks(this) - val withDeps = CommunalInteractorFactory.create() - communalInteractor = withDeps.communalInteractor - communalRepository = withDeps.communalRepository + communalInteractor = kosmos.communalInteractor + communalRepository = kosmos.fakeCommunalRepository underTest = GlanceableHubContainerController( @@ -91,7 +94,12 @@ class GlanceableHubContainerControllerTest : SysuiTestCase() { .thenReturn(bouncerShowingFlow) whenever(shadeInteractor.isAnyFullyExpanded).thenReturn(shadeShowingFlow) - overrideResource(R.dimen.communal_grid_gutter_size, SWIPE_REGION_WIDTH) + overrideResource(R.dimen.communal_right_edge_swipe_region_width, RIGHT_SWIPE_REGION_WIDTH) + overrideResource(R.dimen.communal_top_edge_swipe_region_height, TOP_SWIPE_REGION_WIDTH) + overrideResource( + R.dimen.communal_bottom_edge_swipe_region_height, + BOTTOM_SWIPE_REGION_WIDTH + ) } @Test @@ -132,7 +140,7 @@ class GlanceableHubContainerControllerTest : SysuiTestCase() { initAndAttachContainerView() // Touch events are intercepted. - assertThat(underTest.onTouchEvent(DOWN_IN_SWIPE_REGION_EVENT)).isTrue() + assertThat(underTest.onTouchEvent(DOWN_IN_RIGHT_SWIPE_REGION_EVENT)).isTrue() } @Test @@ -144,7 +152,7 @@ class GlanceableHubContainerControllerTest : SysuiTestCase() { // Initial touch down is intercepted, and so are touches outside of the region, until an up // event is received. - assertThat(underTest.onTouchEvent(DOWN_IN_SWIPE_REGION_EVENT)).isTrue() + assertThat(underTest.onTouchEvent(DOWN_IN_RIGHT_SWIPE_REGION_EVENT)).isTrue() assertThat(underTest.onTouchEvent(MOVE_EVENT)).isTrue() assertThat(underTest.onTouchEvent(UP_EVENT)).isTrue() assertThat(underTest.onTouchEvent(MOVE_EVENT)).isFalse() @@ -165,6 +173,28 @@ class GlanceableHubContainerControllerTest : SysuiTestCase() { } @Test + fun onTouchEvent_topSwipeWhenHubOpen_returnsFalse() { + // Communal is open. + communalRepository.setDesiredScene(CommunalSceneKey.Communal) + + initAndAttachContainerView() + + // Touch event in the top swipe reqgion is not intercepted. + assertThat(underTest.onTouchEvent(DOWN_IN_TOP_SWIPE_REGION_EVENT)).isFalse() + } + + @Test + fun onTouchEvent_bottomSwipeWhenHubOpen_returnsFalse() { + // Communal is open. + communalRepository.setDesiredScene(CommunalSceneKey.Communal) + + initAndAttachContainerView() + + // Touch event in the bottom swipe reqgion is not intercepted. + assertThat(underTest.onTouchEvent(DOWN_IN_BOTTOM_SWIPE_REGION_EVENT)).isFalse() + } + + @Test fun onTouchEvent_communalAndBouncerShowing_doesNotIntercept() { // Communal is open. communalRepository.setDesiredScene(CommunalSceneKey.Communal) @@ -210,11 +240,32 @@ class GlanceableHubContainerControllerTest : SysuiTestCase() { companion object { private const val CONTAINER_WIDTH = 100 private const val CONTAINER_HEIGHT = 100 - private const val SWIPE_REGION_WIDTH = 20 - - private val DOWN_EVENT = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0) - private val DOWN_IN_SWIPE_REGION_EVENT = + private const val RIGHT_SWIPE_REGION_WIDTH = 20 + private const val TOP_SWIPE_REGION_WIDTH = 20 + private const val BOTTOM_SWIPE_REGION_WIDTH = 20 + + private val DOWN_EVENT = + MotionEvent.obtain( + 0L, + 0L, + MotionEvent.ACTION_DOWN, + CONTAINER_WIDTH.toFloat(), + CONTAINER_HEIGHT.toFloat(), + 0 + ) + private val DOWN_IN_RIGHT_SWIPE_REGION_EVENT = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, CONTAINER_WIDTH.toFloat(), 0f, 0) + private val DOWN_IN_TOP_SWIPE_REGION_EVENT = + MotionEvent.obtain( + 0L, + 0L, + MotionEvent.ACTION_DOWN, + 0f, + TOP_SWIPE_REGION_WIDTH.toFloat(), + 0 + ) + private val DOWN_IN_BOTTOM_SWIPE_REGION_EVENT = + MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, CONTAINER_HEIGHT.toFloat(), 0) private val MOVE_EVENT = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_MOVE, 0f, 0f, 0) private val UP_EVENT = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_UP, 0f, 0f, 0) diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java index 11da2376328a..461db8e6166c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java @@ -57,7 +57,6 @@ import com.android.systemui.colorextraction.SysuiColorExtractor; import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository; import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor; import com.android.systemui.communal.domain.interactor.CommunalInteractor; -import com.android.systemui.communal.domain.interactor.CommunalInteractorFactory; import com.android.systemui.deviceentry.domain.interactor.DeviceEntryUdfpsInteractor; import com.android.systemui.dump.DumpManager; import com.android.systemui.flags.FakeFeatureFlagsClassic; @@ -202,8 +201,7 @@ public class NotificationShadeWindowControllerImplTest extends SysuiTestCase { new ConfigurationInteractor(configurationRepository), shadeRepository, () -> sceneInteractor); - CommunalInteractor communalInteractor = - CommunalInteractorFactory.create().getCommunalInteractor(); + CommunalInteractor communalInteractor = mKosmos.getCommunalInteractor(); FakeKeyguardTransitionRepository keyguardTransitionRepository = new FakeKeyguardTransitionRepository(); @@ -228,6 +226,7 @@ public class NotificationShadeWindowControllerImplTest extends SysuiTestCase { powerInteractor, new GlanceableHubTransitions( mTestScope, + mKosmos.getTestDispatcher(), keyguardTransitionInteractor, keyguardTransitionRepository, communalInteractor @@ -249,6 +248,7 @@ public class NotificationShadeWindowControllerImplTest extends SysuiTestCase { mKosmos.getTestDispatcher(), mKosmos.getTestDispatcher(), keyguardInteractor, + communalInteractor, featureFlags, mKeyguardSecurityModel, mSelectedUserInteractor, @@ -303,7 +303,8 @@ public class NotificationShadeWindowControllerImplTest extends SysuiTestCase { mShadeWindowLogger, () -> mSelectedUserInteractor, mUserTracker, - mSceneContainerFlags) { + mSceneContainerFlags, + () -> communalInteractor) { @Override protected boolean isDebuggable() { return false; @@ -451,6 +452,24 @@ public class NotificationShadeWindowControllerImplTest extends SysuiTestCase { } @Test + public void setCommunalShowing_userTimeout() { + setKeyguardShowing(); + clearInvocations(mWindowManager); + + mNotificationShadeWindowController.onCommunalShowingChanged(true); + verify(mWindowManager).updateViewLayout(any(), mLayoutParameters.capture()); + assertThat(mLayoutParameters.getValue().userActivityTimeout) + .isEqualTo(CommunalInteractor.AWAKE_INTERVAL_MS); + clearInvocations(mWindowManager); + + // Bouncer showing over communal overrides communal value + mNotificationShadeWindowController.setBouncerShowing(true); + verify(mWindowManager).updateViewLayout(any(), mLayoutParameters.capture()); + assertThat(mLayoutParameters.getValue().userActivityTimeout) + .isEqualTo(KeyguardViewMediator.AWAKE_INTERVAL_BOUNCER_MS); + } + + @Test public void setKeyguardShowing_notFocusable_byDefault() { mNotificationShadeWindowController.setKeyguardShowing(false); diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerBaseTest.java index 8f46a37bf540..3e0a647d464e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerBaseTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerBaseTest.java @@ -43,7 +43,6 @@ import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepositor import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository; import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor; import com.android.systemui.communal.domain.interactor.CommunalInteractor; -import com.android.systemui.communal.domain.interactor.CommunalInteractorFactory; import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor; import com.android.systemui.deviceentry.domain.interactor.DeviceEntryUdfpsInteractor; import com.android.systemui.dump.DumpManager; @@ -233,8 +232,7 @@ public class QuickSettingsControllerBaseTest extends SysuiTestCase { new ConfigurationInteractor(configurationRepository), mShadeRepository, () -> sceneInteractor); - CommunalInteractor communalInteractor = - CommunalInteractorFactory.create().getCommunalInteractor(); + CommunalInteractor communalInteractor = mKosmos.getCommunalInteractor(); FakeKeyguardTransitionRepository keyguardTransitionRepository = new FakeKeyguardTransitionRepository(); @@ -259,6 +257,7 @@ public class QuickSettingsControllerBaseTest extends SysuiTestCase { powerInteractor, new GlanceableHubTransitions( mTestScope, + mKosmos.getTestDispatcher(), keyguardTransitionInteractor, keyguardTransitionRepository, communalInteractor @@ -280,6 +279,7 @@ public class QuickSettingsControllerBaseTest extends SysuiTestCase { mKosmos.getTestDispatcher(), mKosmos.getTestDispatcher(), keyguardInteractor, + communalInteractor, featureFlags, mock(KeyguardSecurityModel.class), mSelectedUserInteractor, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarStateControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarStateControllerImplTest.kt index 05e866e85112..8cb064dd39a6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarStateControllerImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarStateControllerImplTest.kt @@ -27,7 +27,7 @@ import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepositor import com.android.systemui.classifier.FalsingCollectorFake import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor -import com.android.systemui.communal.domain.interactor.CommunalInteractorFactory +import com.android.systemui.communal.domain.interactor.communalInteractor import com.android.systemui.deviceentry.domain.interactor.DeviceEntryUdfpsInteractor import com.android.systemui.flags.FakeFeatureFlagsClassic import com.android.systemui.keyguard.data.repository.FakeCommandQueue @@ -144,7 +144,7 @@ class StatusBarStateControllerImplTest : SysuiTestCase() { { fromLockscreenTransitionInteractor }, { fromPrimaryBouncerTransitionInteractor } ) - val communalInteractor = CommunalInteractorFactory.create().communalInteractor + val communalInteractor = kosmos.communalInteractor fromLockscreenTransitionInteractor = FromLockscreenTransitionInteractor( keyguardTransitionRepository, @@ -158,6 +158,7 @@ class StatusBarStateControllerImplTest : SysuiTestCase() { powerInteractor, GlanceableHubTransitions( testScope, + testDispatcher, keyguardTransitionInteractor, keyguardTransitionRepository, communalInteractor @@ -180,6 +181,7 @@ class StatusBarStateControllerImplTest : SysuiTestCase() { testDispatcher, testDispatcher, keyguardInteractor, + communalInteractor, featureFlags, mock(), mock(), diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/NotificationStatsLoggerCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/NotificationStatsLoggerCoordinatorTest.kt new file mode 100644 index 000000000000..c29ff416feb9 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/NotificationStatsLoggerCoordinatorTest.kt @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.notification.collection.coordinator + +import android.platform.test.annotations.EnableFlags +import android.service.notification.NotificationListenerService.REASON_CANCEL +import android.testing.AndroidTestingRunner +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.statusbar.notification.collection.NotifPipeline +import com.android.systemui.statusbar.notification.collection.NotificationEntry +import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener +import com.android.systemui.statusbar.notification.shared.NotificationsLiveDataStoreRefactor +import com.android.systemui.statusbar.notification.stack.ui.view.NotificationStatsLogger +import com.android.systemui.util.mockito.mock +import com.android.systemui.util.mockito.whenever +import com.android.systemui.util.mockito.withArgCaptor +import java.util.Optional +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mockito.verify + +@SmallTest +@RunWith(AndroidTestingRunner::class) +@EnableFlags(NotificationsLiveDataStoreRefactor.FLAG_NAME) +class NotificationStatsLoggerCoordinatorTest : SysuiTestCase() { + + private lateinit var collectionListener: NotifCollectionListener + + private val pipeline: NotifPipeline = mock() + private val logger: NotificationStatsLogger = mock() + private val underTest = NotificationStatsLoggerCoordinator(Optional.of(logger)) + + @Before + fun attachPipeline() { + underTest.attach(pipeline) + collectionListener = withArgCaptor { verify(pipeline).addCollectionListener(capture()) } + } + + @Test + fun onEntryAdded_loggerCalled() { + collectionListener.onEntryRemoved(mockEntry("key"), REASON_CANCEL) + + verify(logger).onNotificationRemoved("key") + } + + @Test + fun onEntryRemoved_loggerCalled() { + collectionListener.onEntryUpdated(mockEntry("key")) + + verify(logger).onNotificationUpdated("key") + } + + private fun mockEntry(key: String): NotificationEntry { + return mock { whenever(this.key).thenReturn(key) } + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinatorTest.kt index df547ae5883e..350ed2d9ff22 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinatorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinatorTest.kt @@ -17,9 +17,11 @@ package com.android.systemui.statusbar.notification.collection.coordinator import android.os.UserHandle +import android.platform.test.annotations.EnableFlags import android.service.notification.StatusBarNotification import androidx.test.filters.SmallTest import com.android.keyguard.KeyguardUpdateMonitor +import com.android.systemui.Flags.FLAG_SCREENSHARE_NOTIFICATION_HIDING import com.android.systemui.SysuiTestCase import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.statusbar.NotificationLockscreenUserManager @@ -33,6 +35,7 @@ import com.android.systemui.statusbar.notification.collection.listbuilder.OnBefo import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Invalidator import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Pluggable import com.android.systemui.statusbar.policy.KeyguardStateController +import com.android.systemui.statusbar.policy.SensitiveNotificationProtectionController import com.android.systemui.user.domain.interactor.SelectedUserInteractor import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.eq @@ -55,28 +58,31 @@ class SensitiveContentCoordinatorTest : SysuiTestCase() { val statusBarStateController: StatusBarStateController = mock() val keyguardStateController: KeyguardStateController = mock() val mSelectedUserInteractor: SelectedUserInteractor = mock() + val sensitiveNotificationProtectionController: SensitiveNotificationProtectionController = + mock() val coordinator: SensitiveContentCoordinator = - DaggerTestSensitiveContentCoordinatorComponent - .factory() - .create( - dynamicPrivacyController, - lockscreenUserManager, - keyguardUpdateMonitor, - statusBarStateController, - keyguardStateController, - mSelectedUserInteractor) - .coordinator + DaggerTestSensitiveContentCoordinatorComponent.factory() + .create( + dynamicPrivacyController, + lockscreenUserManager, + keyguardUpdateMonitor, + statusBarStateController, + keyguardStateController, + mSelectedUserInteractor, + sensitiveNotificationProtectionController + ) + .coordinator @Test fun onDynamicPrivacyChanged_invokeInvalidationListener() { coordinator.attach(pipeline) - val invalidator = withArgCaptor<Invalidator> { - verify(pipeline).addPreRenderInvalidator(capture()) - } - val dynamicPrivacyListener = withArgCaptor<DynamicPrivacyController.Listener> { - verify(dynamicPrivacyController).addListener(capture()) - } + val invalidator = + withArgCaptor<Invalidator> { verify(pipeline).addPreRenderInvalidator(capture()) } + val dynamicPrivacyListener = + withArgCaptor<DynamicPrivacyController.Listener> { + verify(dynamicPrivacyController).addListener(capture()) + } val invalidationListener = mock<Pluggable.PluggableListener<Invalidator>>() invalidator.setInvalidationListener(invalidationListener) @@ -89,9 +95,10 @@ class SensitiveContentCoordinatorTest : SysuiTestCase() { @Test fun onBeforeRenderList_deviceUnlocked_notifDoesNotNeedRedaction() { coordinator.attach(pipeline) - val onBeforeRenderListListener = withArgCaptor<OnBeforeRenderListListener> { - verify(pipeline).addOnBeforeRenderListListener(capture()) - } + val onBeforeRenderListListener = + withArgCaptor<OnBeforeRenderListListener> { + verify(pipeline).addOnBeforeRenderListListener(capture()) + } whenever(lockscreenUserManager.currentUserId).thenReturn(1) whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(false) @@ -105,11 +112,59 @@ class SensitiveContentCoordinatorTest : SysuiTestCase() { } @Test + @EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING) + fun onBeforeRenderList_deviceUnlocked_notifDoesNotNeedRedaction_sensitiveActive() { + coordinator.attach(pipeline) + val onBeforeRenderListListener = + withArgCaptor<OnBeforeRenderListListener> { + verify(pipeline).addOnBeforeRenderListListener(capture()) + } + + whenever(lockscreenUserManager.currentUserId).thenReturn(1) + whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(false) + whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(true) + whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(false) + val entry = fakeNotification(1, false) + whenever(sensitiveNotificationProtectionController.isSensitiveStateActive).thenReturn(true) + + onBeforeRenderListListener.onBeforeRenderList(listOf(entry)) + + verify(entry.representativeEntry!!).setSensitive(false, true) + } + + @Test + @EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING) + fun onBeforeRenderList_deviceUnlocked_notifDoesNotNeedRedaction_shouldProtectNotification() { + coordinator.attach(pipeline) + val onBeforeRenderListListener = + withArgCaptor<OnBeforeRenderListListener> { + verify(pipeline).addOnBeforeRenderListListener(capture()) + } + + whenever(lockscreenUserManager.currentUserId).thenReturn(1) + whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(false) + whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(true) + whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(false) + val entry = fakeNotification(1, false) + whenever( + sensitiveNotificationProtectionController.shouldProtectNotification( + entry.getRepresentativeEntry() + ) + ) + .thenReturn(true) + + onBeforeRenderListListener.onBeforeRenderList(listOf(entry)) + + verify(entry.representativeEntry!!).setSensitive(true, false) + } + + @Test fun onBeforeRenderList_deviceUnlocked_notifWouldNeedRedaction() { coordinator.attach(pipeline) - val onBeforeRenderListListener = withArgCaptor<OnBeforeRenderListListener> { - verify(pipeline).addOnBeforeRenderListListener(capture()) - } + val onBeforeRenderListListener = + withArgCaptor<OnBeforeRenderListListener> { + verify(pipeline).addOnBeforeRenderListListener(capture()) + } whenever(lockscreenUserManager.currentUserId).thenReturn(1) whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(false) @@ -123,11 +178,59 @@ class SensitiveContentCoordinatorTest : SysuiTestCase() { } @Test + @EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING) + fun onBeforeRenderList_deviceUnlocked_notifWouldNeedRedaction_sensitiveActive() { + coordinator.attach(pipeline) + val onBeforeRenderListListener = + withArgCaptor<OnBeforeRenderListListener> { + verify(pipeline).addOnBeforeRenderListListener(capture()) + } + + whenever(lockscreenUserManager.currentUserId).thenReturn(1) + whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(false) + whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(true) + whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(false) + val entry = fakeNotification(1, true) + whenever(sensitiveNotificationProtectionController.isSensitiveStateActive).thenReturn(true) + + onBeforeRenderListListener.onBeforeRenderList(listOf(entry)) + + verify(entry.representativeEntry!!).setSensitive(false, true) + } + + @Test + @EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING) + fun onBeforeRenderList_deviceUnlocked_notifWouldNeedRedaction_shouldProtectNotification() { + coordinator.attach(pipeline) + val onBeforeRenderListListener = + withArgCaptor<OnBeforeRenderListListener> { + verify(pipeline).addOnBeforeRenderListListener(capture()) + } + + whenever(lockscreenUserManager.currentUserId).thenReturn(1) + whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(false) + whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(true) + whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(false) + val entry = fakeNotification(1, true) + whenever( + sensitiveNotificationProtectionController.shouldProtectNotification( + entry.getRepresentativeEntry() + ) + ) + .thenReturn(true) + + onBeforeRenderListListener.onBeforeRenderList(listOf(entry)) + + verify(entry.representativeEntry!!).setSensitive(true, false) + } + + @Test fun onBeforeRenderList_deviceLocked_userAllowsPublicNotifs() { coordinator.attach(pipeline) - val onBeforeRenderListListener = withArgCaptor<OnBeforeRenderListListener> { - verify(pipeline).addOnBeforeRenderListListener(capture()) - } + val onBeforeRenderListListener = + withArgCaptor<OnBeforeRenderListListener> { + verify(pipeline).addOnBeforeRenderListListener(capture()) + } whenever(lockscreenUserManager.currentUserId).thenReturn(1) whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true) @@ -141,17 +244,87 @@ class SensitiveContentCoordinatorTest : SysuiTestCase() { } @Test + @EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING) + fun onBeforeRenderList_deviceLocked_userAllowsPublicNotifs_sensitiveActive() { + coordinator.attach(pipeline) + val onBeforeRenderListListener = + withArgCaptor<OnBeforeRenderListListener> { + verify(pipeline).addOnBeforeRenderListListener(capture()) + } + + whenever(lockscreenUserManager.currentUserId).thenReturn(1) + whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true) + whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(true) + whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(false) + val entry = fakeNotification(1, false) + whenever(sensitiveNotificationProtectionController.isSensitiveStateActive).thenReturn(true) + + onBeforeRenderListListener.onBeforeRenderList(listOf(entry)) + + verify(entry.representativeEntry!!).setSensitive(false, true) + } + + @Test + @EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING) + fun onBeforeRenderList_deviceLocked_userAllowsPublicNotifs_shouldProtectNotification() { + coordinator.attach(pipeline) + val onBeforeRenderListListener = + withArgCaptor<OnBeforeRenderListListener> { + verify(pipeline).addOnBeforeRenderListListener(capture()) + } + + whenever(lockscreenUserManager.currentUserId).thenReturn(1) + whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true) + whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(true) + whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(false) + val entry = fakeNotification(1, false) + whenever( + sensitiveNotificationProtectionController.shouldProtectNotification( + entry.getRepresentativeEntry() + ) + ) + .thenReturn(true) + + onBeforeRenderListListener.onBeforeRenderList(listOf(entry)) + + verify(entry.representativeEntry!!).setSensitive(true, false) + } + + @Test fun onBeforeRenderList_deviceLocked_userDisallowsPublicNotifs_notifDoesNotNeedRedaction() { coordinator.attach(pipeline) - val onBeforeRenderListListener = withArgCaptor<OnBeforeRenderListListener> { - verify(pipeline).addOnBeforeRenderListListener(capture()) - } + val onBeforeRenderListListener = + withArgCaptor<OnBeforeRenderListListener> { + verify(pipeline).addOnBeforeRenderListListener(capture()) + } + + whenever(lockscreenUserManager.currentUserId).thenReturn(1) + whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true) + whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(false) + whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(false) + val entry = fakeNotification(1, false) + + onBeforeRenderListListener.onBeforeRenderList(listOf(entry)) + + verify(entry.representativeEntry!!).setSensitive(false, true) + } + + @Test + @EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING) + @Suppress("ktlint:standard:max-line-length") + fun onBeforeRenderList_deviceLocked_userDisallowsPublicNotifs_notifDoesNotNeedRedaction_sensitiveActive() { + coordinator.attach(pipeline) + val onBeforeRenderListListener = + withArgCaptor<OnBeforeRenderListListener> { + verify(pipeline).addOnBeforeRenderListListener(capture()) + } whenever(lockscreenUserManager.currentUserId).thenReturn(1) whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true) whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(false) whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(false) val entry = fakeNotification(1, false) + whenever(sensitiveNotificationProtectionController.isSensitiveStateActive).thenReturn(true) onBeforeRenderListListener.onBeforeRenderList(listOf(entry)) @@ -159,17 +332,92 @@ class SensitiveContentCoordinatorTest : SysuiTestCase() { } @Test + @EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING) + @Suppress("ktlint:standard:max-line-length") + fun onBeforeRenderList_deviceLocked_userDisallowsPublicNotifs_notifDoesNotNeedRedaction_shouldProtectNotification() { + coordinator.attach(pipeline) + val onBeforeRenderListListener = + withArgCaptor<OnBeforeRenderListListener> { + verify(pipeline).addOnBeforeRenderListListener(capture()) + } + + whenever(lockscreenUserManager.currentUserId).thenReturn(1) + whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true) + whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(false) + whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(false) + val entry = fakeNotification(1, false) + whenever( + sensitiveNotificationProtectionController.shouldProtectNotification( + entry.getRepresentativeEntry() + ) + ) + .thenReturn(true) + + onBeforeRenderListListener.onBeforeRenderList(listOf(entry)) + + verify(entry.representativeEntry!!).setSensitive(true, true) + } + + @Test fun onBeforeRenderList_deviceLocked_notifNeedsRedaction() { coordinator.attach(pipeline) - val onBeforeRenderListListener = withArgCaptor<OnBeforeRenderListListener> { - verify(pipeline).addOnBeforeRenderListListener(capture()) - } + val onBeforeRenderListListener = + withArgCaptor<OnBeforeRenderListListener> { + verify(pipeline).addOnBeforeRenderListListener(capture()) + } + + whenever(lockscreenUserManager.currentUserId).thenReturn(1) + whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true) + whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(false) + whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(false) + val entry = fakeNotification(1, true) + + onBeforeRenderListListener.onBeforeRenderList(listOf(entry)) + + verify(entry.representativeEntry!!).setSensitive(true, true) + } + + @Test + @EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING) + fun onBeforeRenderList_deviceLocked_notifNeedsRedaction_sensitiveActive() { + coordinator.attach(pipeline) + val onBeforeRenderListListener = + withArgCaptor<OnBeforeRenderListListener> { + verify(pipeline).addOnBeforeRenderListListener(capture()) + } whenever(lockscreenUserManager.currentUserId).thenReturn(1) whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true) whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(false) whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(false) val entry = fakeNotification(1, true) + whenever(sensitiveNotificationProtectionController.isSensitiveStateActive).thenReturn(true) + + onBeforeRenderListListener.onBeforeRenderList(listOf(entry)) + + verify(entry.representativeEntry!!).setSensitive(true, true) + } + + @Test + @EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING) + fun onBeforeRenderList_deviceLocked_notifNeedsRedaction_shouldProtectNotification() { + coordinator.attach(pipeline) + val onBeforeRenderListListener = + withArgCaptor<OnBeforeRenderListListener> { + verify(pipeline).addOnBeforeRenderListListener(capture()) + } + + whenever(lockscreenUserManager.currentUserId).thenReturn(1) + whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true) + whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(false) + whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(false) + val entry = fakeNotification(1, true) + whenever( + sensitiveNotificationProtectionController.shouldProtectNotification( + entry.getRepresentativeEntry() + ) + ) + .thenReturn(true) onBeforeRenderListListener.onBeforeRenderList(listOf(entry)) @@ -179,15 +427,37 @@ class SensitiveContentCoordinatorTest : SysuiTestCase() { @Test fun onBeforeRenderList_deviceDynamicallyUnlocked_notifNeedsRedaction() { coordinator.attach(pipeline) - val onBeforeRenderListListener = withArgCaptor<OnBeforeRenderListListener> { - verify(pipeline).addOnBeforeRenderListListener(capture()) - } + val onBeforeRenderListListener = + withArgCaptor<OnBeforeRenderListListener> { + verify(pipeline).addOnBeforeRenderListListener(capture()) + } + + whenever(lockscreenUserManager.currentUserId).thenReturn(1) + whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true) + whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(false) + whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(true) + val entry = fakeNotification(1, true) + + onBeforeRenderListListener.onBeforeRenderList(listOf(entry)) + + verify(entry.representativeEntry!!).setSensitive(false, true) + } + + @Test + @EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING) + fun onBeforeRenderList_deviceDynamicallyUnlocked_notifNeedsRedaction_sensitiveActive() { + coordinator.attach(pipeline) + val onBeforeRenderListListener = + withArgCaptor<OnBeforeRenderListListener> { + verify(pipeline).addOnBeforeRenderListListener(capture()) + } whenever(lockscreenUserManager.currentUserId).thenReturn(1) whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true) whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(false) whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(true) val entry = fakeNotification(1, true) + whenever(sensitiveNotificationProtectionController.isSensitiveStateActive).thenReturn(true) onBeforeRenderListListener.onBeforeRenderList(listOf(entry)) @@ -195,19 +465,96 @@ class SensitiveContentCoordinatorTest : SysuiTestCase() { } @Test + @EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING) + @Suppress("ktlint:standard:max-line-length") + fun onBeforeRenderList_deviceDynamicallyUnlocked_notifNeedsRedaction_shouldProtectNotification() { + coordinator.attach(pipeline) + val onBeforeRenderListListener = + withArgCaptor<OnBeforeRenderListListener> { + verify(pipeline).addOnBeforeRenderListListener(capture()) + } + + whenever(lockscreenUserManager.currentUserId).thenReturn(1) + whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true) + whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(false) + whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(true) + val entry = fakeNotification(1, true) + whenever( + sensitiveNotificationProtectionController.shouldProtectNotification( + entry.getRepresentativeEntry() + ) + ) + .thenReturn(true) + + onBeforeRenderListListener.onBeforeRenderList(listOf(entry)) + + verify(entry.representativeEntry!!).setSensitive(true, true) + } + + @Test fun onBeforeRenderList_deviceDynamicallyUnlocked_notifUserNeedsWorkChallenge() { coordinator.attach(pipeline) - val onBeforeRenderListListener = withArgCaptor<OnBeforeRenderListListener> { - verify(pipeline).addOnBeforeRenderListListener(capture()) - } + val onBeforeRenderListListener = + withArgCaptor<OnBeforeRenderListListener> { + verify(pipeline).addOnBeforeRenderListListener(capture()) + } + + whenever(lockscreenUserManager.currentUserId).thenReturn(1) + whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true) + whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(false) + whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(true) + whenever(lockscreenUserManager.needsSeparateWorkChallenge(2)).thenReturn(true) + val entry = fakeNotification(2, true) + + onBeforeRenderListListener.onBeforeRenderList(listOf(entry)) + + verify(entry.representativeEntry!!).setSensitive(true, true) + } + + @Test + @EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING) + fun onBeforeRenderList_deviceDynamicallyUnlocked_notifUserNeedsWorkChallenge_sensitiveActive() { + coordinator.attach(pipeline) + val onBeforeRenderListListener = + withArgCaptor<OnBeforeRenderListListener> { + verify(pipeline).addOnBeforeRenderListListener(capture()) + } whenever(lockscreenUserManager.currentUserId).thenReturn(1) whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true) whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(false) whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(true) whenever(lockscreenUserManager.needsSeparateWorkChallenge(2)).thenReturn(true) + val entry = fakeNotification(2, true) + whenever(sensitiveNotificationProtectionController.isSensitiveStateActive).thenReturn(true) + + onBeforeRenderListListener.onBeforeRenderList(listOf(entry)) + + verify(entry.representativeEntry!!).setSensitive(true, true) + } + @Test + @EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING) + @Suppress("ktlint:standard:max-line-length") + fun onBeforeRenderList_deviceDynamicallyUnlocked_notifUserNeedsWorkChallenge_shouldProtectNotification() { + coordinator.attach(pipeline) + val onBeforeRenderListListener = + withArgCaptor<OnBeforeRenderListListener> { + verify(pipeline).addOnBeforeRenderListListener(capture()) + } + + whenever(lockscreenUserManager.currentUserId).thenReturn(1) + whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true) + whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(false) + whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(true) + whenever(lockscreenUserManager.needsSeparateWorkChallenge(2)).thenReturn(true) val entry = fakeNotification(2, true) + whenever( + sensitiveNotificationProtectionController.shouldProtectNotification( + entry.getRepresentativeEntry() + ) + ) + .thenReturn(true) onBeforeRenderListListener.onBeforeRenderList(listOf(entry)) @@ -217,9 +564,10 @@ class SensitiveContentCoordinatorTest : SysuiTestCase() { @Test fun onBeforeRenderList_deviceDynamicallyUnlocked_deviceBiometricBypassingLockScreen() { coordinator.attach(pipeline) - val onBeforeRenderListListener = withArgCaptor<OnBeforeRenderListListener> { - verify(pipeline).addOnBeforeRenderListListener(capture()) - } + val onBeforeRenderListListener = + withArgCaptor<OnBeforeRenderListListener> { + verify(pipeline).addOnBeforeRenderListListener(capture()) + } whenever(lockscreenUserManager.currentUserId).thenReturn(1) whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true) @@ -227,9 +575,11 @@ class SensitiveContentCoordinatorTest : SysuiTestCase() { whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(true) whenever(statusBarStateController.getState()).thenReturn(StatusBarState.KEYGUARD) whenever(keyguardUpdateMonitor.getUserUnlockedWithBiometricAndIsBypassing(any())) - .thenReturn(true) - + .thenReturn(true) val entry = fakeNotification(2, true) + whenever(sensitiveNotificationProtectionController.isSensitiveStateActive).thenReturn(true) + whenever(sensitiveNotificationProtectionController.shouldProtectNotification(any())) + .thenReturn(true) onBeforeRenderListListener.onBeforeRenderList(listOf(entry)) @@ -237,15 +587,11 @@ class SensitiveContentCoordinatorTest : SysuiTestCase() { } private fun fakeNotification(notifUserId: Int, needsRedaction: Boolean): ListEntry { - val mockUserHandle = mock<UserHandle>().apply { - whenever(identifier).thenReturn(notifUserId) - } - val mockSbn: StatusBarNotification = mock<StatusBarNotification>().apply { - whenever(user).thenReturn(mockUserHandle) - } - val mockEntry = mock<NotificationEntry>().apply { - whenever(sbn).thenReturn(mockSbn) - } + val mockUserHandle = + mock<UserHandle>().apply { whenever(identifier).thenReturn(notifUserId) } + val mockSbn: StatusBarNotification = + mock<StatusBarNotification>().apply { whenever(user).thenReturn(mockUserHandle) } + val mockEntry = mock<NotificationEntry>().apply { whenever(sbn).thenReturn(mockSbn) } whenever(lockscreenUserManager.needsRedaction(mockEntry)).thenReturn(needsRedaction) whenever(mockEntry.rowExists()).thenReturn(true) return object : ListEntry("key", 0) { @@ -268,6 +614,8 @@ interface TestSensitiveContentCoordinatorComponent { @BindsInstance statusBarStateController: StatusBarStateController, @BindsInstance keyguardStateController: KeyguardStateController, @BindsInstance selectedUserInteractor: SelectedUserInteractor, + @BindsInstance + sensitiveNotificationProtectionController: SensitiveNotificationProtectionController, ): TestSensitiveContentCoordinatorComponent } } 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 89f826b2049d..1ab4c32c7d08 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 @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.notification.stack; +import static com.android.systemui.Flags.FLAG_SCREENSHARE_NOTIFICATION_HIDING; import static com.android.systemui.log.LogBufferHelperKt.logcatLogBuffer; import static com.android.systemui.statusbar.StatusBarState.KEYGUARD; import static com.android.systemui.statusbar.StatusBarState.SHADE; @@ -32,6 +33,7 @@ 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.verifyZeroInteractions; import static org.mockito.Mockito.when; import static kotlinx.coroutines.flow.FlowKt.emptyFlow; @@ -39,6 +41,7 @@ import static kotlinx.coroutines.test.TestCoroutineDispatchersKt.StandardTestDis import android.metrics.LogMaker; import android.platform.test.annotations.DisableFlags; +import android.platform.test.annotations.EnableFlags; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.view.View; @@ -101,6 +104,7 @@ import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.HeadsUpManager; import com.android.systemui.statusbar.policy.ResourcesSplitShadeStateController; +import com.android.systemui.statusbar.policy.SensitiveNotificationProtectionController; import com.android.systemui.statusbar.policy.ZenModeController; import com.android.systemui.tuner.TunerService; import com.android.systemui.util.settings.SecureSettings; @@ -172,10 +176,16 @@ public class NotificationStackScrollLayoutControllerTest extends SysuiTestCase { @Mock private ActivityStarter mActivityStarter; @Mock private KeyguardTransitionRepository mKeyguardTransitionRepo; @Mock private NotificationListViewBinder mViewBinder; + @Mock + private SensitiveNotificationProtectionController mSensitiveNotificationProtectionController; + + @Captor + private ArgumentCaptor<Runnable> mSensitiveStateListenerArgumentCaptor; @Captor private ArgumentCaptor<StatusBarStateController.StateListener> mStateListenerArgumentCaptor; + private final ActiveNotificationListRepository mActiveNotificationsRepository = new ActiveNotificationListRepository(); @@ -386,6 +396,23 @@ public class NotificationStackScrollLayoutControllerTest extends SysuiTestCase { } @Test + public void testOnUserChange_verifyNotSensitive() { + when(mNotificationLockscreenUserManager.isAnyProfilePublicMode()).thenReturn(false); + initController(/* viewIsAttached= */ true); + + ArgumentCaptor<UserChangedListener> userChangedCaptor = ArgumentCaptor + .forClass(UserChangedListener.class); + + verify(mNotificationLockscreenUserManager) + .addUserChangedListener(userChangedCaptor.capture()); + reset(mNotificationStackScrollLayout); + + UserChangedListener changedListener = userChangedCaptor.getValue(); + changedListener.onUserChanged(0); + verify(mNotificationStackScrollLayout).updateSensitiveness(false, false); + } + + @Test public void testOnUserChange_verifySensitiveProfile() { when(mNotificationLockscreenUserManager.isAnyProfilePublicMode()).thenReturn(true); initController(/* viewIsAttached= */ true); @@ -403,6 +430,80 @@ public class NotificationStackScrollLayoutControllerTest extends SysuiTestCase { } @Test + @EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING) + public void testOnUserChange_verifyNotSensitive_screenshareNotificationHidingEnabled() { + when(mNotificationLockscreenUserManager.isAnyProfilePublicMode()).thenReturn(false); + when(mSensitiveNotificationProtectionController.isSensitiveStateActive()).thenReturn(false); + + initController(/* viewIsAttached= */ true); + + ArgumentCaptor<UserChangedListener> userChangedCaptor = ArgumentCaptor + .forClass(UserChangedListener.class); + + verify(mNotificationLockscreenUserManager) + .addUserChangedListener(userChangedCaptor.capture()); + reset(mNotificationStackScrollLayout); + + UserChangedListener changedListener = userChangedCaptor.getValue(); + changedListener.onUserChanged(0); + verify(mNotificationStackScrollLayout).updateSensitiveness(false, false); + } + + @Test + @EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING) + public void testOnUserChange_verifySensitiveProfile_screenshareNotificationHidingEnabled() { + when(mNotificationLockscreenUserManager.isAnyProfilePublicMode()).thenReturn(true); + when(mSensitiveNotificationProtectionController.isSensitiveStateActive()).thenReturn(false); + + initController(/* viewIsAttached= */ true); + + ArgumentCaptor<UserChangedListener> userChangedCaptor = ArgumentCaptor + .forClass(UserChangedListener.class); + + verify(mNotificationLockscreenUserManager) + .addUserChangedListener(userChangedCaptor.capture()); + reset(mNotificationStackScrollLayout); + + UserChangedListener changedListener = userChangedCaptor.getValue(); + changedListener.onUserChanged(0); + verify(mNotificationStackScrollLayout).updateSensitiveness(false, true); + } + + @Test + @EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING) + public void testOnUserChange_verifySensitiveActive_screenshareNotificationHidingEnabled() { + when(mNotificationLockscreenUserManager.isAnyProfilePublicMode()).thenReturn(false); + when(mSensitiveNotificationProtectionController.isSensitiveStateActive()).thenReturn(true); + initController(/* viewIsAttached= */ true); + + ArgumentCaptor<UserChangedListener> userChangedCaptor = ArgumentCaptor + .forClass(UserChangedListener.class); + + verify(mNotificationLockscreenUserManager) + .addUserChangedListener(userChangedCaptor.capture()); + reset(mNotificationStackScrollLayout); + + UserChangedListener changedListener = userChangedCaptor.getValue(); + changedListener.onUserChanged(0); + verify(mNotificationStackScrollLayout).updateSensitiveness(false, true); + } + + @Test + public void testOnStatePostChange_verifyNotSensitive() { + when(mNotificationLockscreenUserManager.isAnyProfilePublicMode()).thenReturn(false); + + initController(/* viewIsAttached= */ true); + verify(mSysuiStatusBarStateController).addCallback( + mStateListenerArgumentCaptor.capture(), anyInt()); + + StatusBarStateController.StateListener stateListener = + mStateListenerArgumentCaptor.getValue(); + + stateListener.onStatePostChange(); + verify(mNotificationStackScrollLayout).updateSensitiveness(false, false); + } + + @Test public void testOnStatePostChange_verifyIfProfileIsPublic() { when(mNotificationLockscreenUserManager.isAnyProfilePublicMode()).thenReturn(true); @@ -418,6 +519,194 @@ public class NotificationStackScrollLayoutControllerTest extends SysuiTestCase { } @Test + @EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING) + public void testOnStatePostChange_verifyNotSensitive_screenshareNotificationHidingEnabled() { + when(mNotificationLockscreenUserManager.isAnyProfilePublicMode()).thenReturn(false); + when(mSensitiveNotificationProtectionController.isSensitiveStateActive()).thenReturn(false); + + initController(/* viewIsAttached= */ true); + verify(mSysuiStatusBarStateController).addCallback( + mStateListenerArgumentCaptor.capture(), anyInt()); + + StatusBarStateController.StateListener stateListener = + mStateListenerArgumentCaptor.getValue(); + + stateListener.onStatePostChange(); + verify(mNotificationStackScrollLayout).updateSensitiveness(false, false); + } + + @Test + @EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING) + public void testOnStatePostChange_verifyIfProfileIsPublic_screenshareNotificationHidingEnabled( + ) { + when(mNotificationLockscreenUserManager.isAnyProfilePublicMode()).thenReturn(true); + when(mSensitiveNotificationProtectionController.isSensitiveStateActive()).thenReturn(false); + + initController(/* viewIsAttached= */ true); + verify(mSysuiStatusBarStateController).addCallback( + mStateListenerArgumentCaptor.capture(), anyInt()); + + StatusBarStateController.StateListener stateListener = + mStateListenerArgumentCaptor.getValue(); + + stateListener.onStatePostChange(); + verify(mNotificationStackScrollLayout).updateSensitiveness(false, true); + } + + @Test + @EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING) + public void testOnStatePostChange_verifyIfSensitiveActive_screenshareNotificationHidingEnabled( + ) { + when(mNotificationLockscreenUserManager.isAnyProfilePublicMode()).thenReturn(false); + when(mSensitiveNotificationProtectionController.isSensitiveStateActive()).thenReturn(true); + + initController(/* viewIsAttached= */ true); + verify(mSysuiStatusBarStateController).addCallback( + mStateListenerArgumentCaptor.capture(), anyInt()); + + StatusBarStateController.StateListener stateListener = + mStateListenerArgumentCaptor.getValue(); + + stateListener.onStatePostChange(); + verify(mNotificationStackScrollLayout).updateSensitiveness(false, true); + } + + @Test + public void testOnStatePostChange_goingFullShade_verifyNotSensitive() { + when(mNotificationLockscreenUserManager.isAnyProfilePublicMode()).thenReturn(false); + when(mSysuiStatusBarStateController.goingToFullShade()).thenReturn(true); + + initController(/* viewIsAttached= */ true); + verify(mSysuiStatusBarStateController).addCallback( + mStateListenerArgumentCaptor.capture(), anyInt()); + + StatusBarStateController.StateListener stateListener = + mStateListenerArgumentCaptor.getValue(); + + stateListener.onStatePostChange(); + verify(mNotificationStackScrollLayout).updateSensitiveness(true, false); + } + + @Test + public void testOnStatePostChange_goingFullShade_verifyIfProfileIsPublic() { + when(mNotificationLockscreenUserManager.isAnyProfilePublicMode()).thenReturn(true); + when(mSysuiStatusBarStateController.goingToFullShade()).thenReturn(true); + + initController(/* viewIsAttached= */ true); + verify(mSysuiStatusBarStateController).addCallback( + mStateListenerArgumentCaptor.capture(), anyInt()); + + StatusBarStateController.StateListener stateListener = + mStateListenerArgumentCaptor.getValue(); + + stateListener.onStatePostChange(); + verify(mNotificationStackScrollLayout).updateSensitiveness(true, true); + } + + @Test + @EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING) + public void testOnStatePostChange_goingFullShade_verifyNotSensitive_screenshareHideEnabled( + ) { + when(mNotificationLockscreenUserManager.isAnyProfilePublicMode()).thenReturn(false); + when(mSysuiStatusBarStateController.goingToFullShade()).thenReturn(true); + when(mSensitiveNotificationProtectionController.isSensitiveStateActive()).thenReturn(false); + + initController(/* viewIsAttached= */ true); + verify(mSysuiStatusBarStateController).addCallback( + mStateListenerArgumentCaptor.capture(), anyInt()); + + StatusBarStateController.StateListener stateListener = + mStateListenerArgumentCaptor.getValue(); + + stateListener.onStatePostChange(); + verify(mNotificationStackScrollLayout).updateSensitiveness(true, false); + } + + @Test + @EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING) + public void testOnStatePostChange_goingFullShade_verifyProfileIsPublic_screenshareHideEnabled( + ) { + when(mNotificationLockscreenUserManager.isAnyProfilePublicMode()).thenReturn(true); + when(mSysuiStatusBarStateController.goingToFullShade()).thenReturn(true); + when(mSensitiveNotificationProtectionController.isSensitiveStateActive()).thenReturn(false); + + initController(/* viewIsAttached= */ true); + verify(mSysuiStatusBarStateController).addCallback( + mStateListenerArgumentCaptor.capture(), anyInt()); + + StatusBarStateController.StateListener stateListener = + mStateListenerArgumentCaptor.getValue(); + + stateListener.onStatePostChange(); + verify(mNotificationStackScrollLayout).updateSensitiveness(true, true); + } + + @Test + @EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING) + public void testOnStatePostChange_goingFullShade_verifySensitiveActive_screenshareHideEnabled( + ) { + when(mNotificationLockscreenUserManager.isAnyProfilePublicMode()).thenReturn(false); + when(mSysuiStatusBarStateController.goingToFullShade()).thenReturn(true); + when(mSensitiveNotificationProtectionController.isSensitiveStateActive()).thenReturn(true); + + initController(/* viewIsAttached= */ true); + verify(mSysuiStatusBarStateController).addCallback( + mStateListenerArgumentCaptor.capture(), anyInt()); + + StatusBarStateController.StateListener stateListener = + mStateListenerArgumentCaptor.getValue(); + + stateListener.onStatePostChange(); + verify(mNotificationStackScrollLayout).updateSensitiveness(false, true); + } + + @Test + @EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING) + public void testOnProjectionStateChanged_verifyNotSensitive() { + when(mNotificationLockscreenUserManager.isAnyProfilePublicMode()).thenReturn(false); + when(mSensitiveNotificationProtectionController.isSensitiveStateActive()) + .thenReturn(false); + + initController(/* viewIsAttached= */ true); + verify(mSensitiveNotificationProtectionController) + .registerSensitiveStateListener(mSensitiveStateListenerArgumentCaptor.capture()); + + mSensitiveStateListenerArgumentCaptor.getValue().run(); + + verify(mNotificationStackScrollLayout).updateSensitiveness(false, false); + } + + @Test + @EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING) + public void testOnProjectionStateChanged_verifyIfProfileIsPublic() { + when(mNotificationLockscreenUserManager.isAnyProfilePublicMode()).thenReturn(true); + when(mSensitiveNotificationProtectionController.isSensitiveStateActive()).thenReturn(false); + + initController(/* viewIsAttached= */ true); + verify(mSensitiveNotificationProtectionController) + .registerSensitiveStateListener(mSensitiveStateListenerArgumentCaptor.capture()); + + mSensitiveStateListenerArgumentCaptor.getValue().run(); + + verify(mNotificationStackScrollLayout).updateSensitiveness(false, true); + } + + @Test + @EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING) + public void testOnProjectionStateChanged_verifyIfSensitiveActive() { + when(mNotificationLockscreenUserManager.isAnyProfilePublicMode()).thenReturn(false); + when(mSensitiveNotificationProtectionController.isSensitiveStateActive()).thenReturn(true); + + initController(/* viewIsAttached= */ true); + verify(mSensitiveNotificationProtectionController) + .registerSensitiveStateListener(mSensitiveStateListenerArgumentCaptor.capture()); + + mSensitiveStateListenerArgumentCaptor.getValue().run(); + + verify(mNotificationStackScrollLayout).updateSensitiveness(false, true); + } + + @Test public void testOnMenuShownLogging() { ExpandableNotificationRow row = mock(ExpandableNotificationRow.class, RETURNS_DEEP_STUBS); when(row.getEntry().getSbn().getLogMaker()).thenReturn(new LogMaker( @@ -666,6 +955,20 @@ public class NotificationStackScrollLayoutControllerTest extends SysuiTestCase { verify(mNotificationStackScrollLayout).updateEmptyShadeView(eq(false), anyBoolean()); } + @Test + @DisableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING) + public void sensitiveNotificationProtectionControllerListenerNotRegistered() { + initController(/* viewIsAttached= */ true); + verifyZeroInteractions(mSensitiveNotificationProtectionController); + } + + @Test + @EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING) + public void sensitiveNotificationProtectionControllerListenerRegistered() { + initController(/* viewIsAttached= */ true); + verify(mSensitiveNotificationProtectionController).registerSensitiveStateListener(any()); + } + private LogMaker logMatcher(int category, int type) { return argThat(new LogMatcher(category, type)); } @@ -744,7 +1047,8 @@ public class NotificationStackScrollLayoutControllerTest extends SysuiTestCase { mSecureSettings, mock(NotificationDismissibilityProvider.class), mActivityStarter, - new ResourcesSplitShadeStateController()); + new ResourcesSplitShadeStateController(), + mSensitiveNotificationProtectionController); } static class LogMatcher implements ArgumentMatcher<LogMaker> { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/view/NotificationStatsLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/view/NotificationStatsLoggerTest.kt index d7d1ffcc3339..c61756c42895 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/view/NotificationStatsLoggerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/view/NotificationStatsLoggerTest.kt @@ -67,7 +67,7 @@ class NotificationStatsLoggerTest : SysuiTestCase() { // AND they're visible val (ranks, locations) = fakeNotificationMaps("key0", "key1") val callable = Callable { locations } - underTest.onNotificationListUpdated(callable, ranks) + underTest.onNotificationLocationsChanged(callable, ranks) runCurrent() // THEN visibility changes are reported @@ -103,13 +103,13 @@ class NotificationStatsLoggerTest : SysuiTestCase() { // GIVEN some visible Notifications are reported val (ranks, locations) = fakeNotificationMaps("key0", "key1") val callable = Callable { locations } - underTest.onNotificationListUpdated(callable, ranks) + underTest.onNotificationLocationsChanged(callable, ranks) runCurrent() clearInvocations(mockStatusBarService, mockNotificationListenerService) // WHEN the same Notifications are removed val emptyCallable = Callable { emptyMap<String, Int>() } - underTest.onNotificationListUpdated(emptyCallable, emptyMap()) + underTest.onNotificationLocationsChanged(emptyCallable, emptyMap()) runCurrent() // THEN visibility changes are reported @@ -140,13 +140,13 @@ class NotificationStatsLoggerTest : SysuiTestCase() { // GIVEN some visible Notifications are reported val (ranks, locations) = fakeNotificationMaps("key0", "key1") val callable = Callable { locations } - underTest.onNotificationListUpdated(callable, ranks) + underTest.onNotificationLocationsChanged(callable, ranks) runCurrent() clearInvocations(mockStatusBarService, mockNotificationListenerService) // WHEN the same Notifications are becoming invisible val emptyCallable = Callable { emptyMap<String, Int>() } - underTest.onNotificationListUpdated(emptyCallable, ranks) + underTest.onNotificationLocationsChanged(emptyCallable, ranks) runCurrent() // THEN visibility changes are reported @@ -176,13 +176,13 @@ class NotificationStatsLoggerTest : SysuiTestCase() { testScope.runTest { // GIVEN some visible Notifications are reported val (ranks, locations) = fakeNotificationMaps("key0", "key1") - underTest.onNotificationListUpdated({ locations }, ranks) + underTest.onNotificationLocationsChanged({ locations }, ranks) runCurrent() clearInvocations(mockStatusBarService, mockNotificationListenerService) // WHEN the reported Notifications are changing positions val (newRanks, newLocations) = fakeNotificationMaps("key1", "key0") - underTest.onNotificationListUpdated({ newLocations }, newRanks) + underTest.onNotificationLocationsChanged({ newLocations }, newRanks) runCurrent() // THEN no visibility changes are reported @@ -195,13 +195,13 @@ class NotificationStatsLoggerTest : SysuiTestCase() { // GIVEN some visible Notifications are reported val (ranks, locations) = fakeNotificationMaps("key0", "key1", "key2") val callable = spy(Callable { locations }) - underTest.onNotificationListUpdated(callable, ranks) + underTest.onNotificationLocationsChanged(callable, ranks) runCurrent() clearInvocations(callable) // WHEN a new update comes val otherCallable = spy(Callable { locations }) - underTest.onNotificationListUpdated(otherCallable, ranks) + underTest.onNotificationLocationsChanged(otherCallable, ranks) runCurrent() // THEN we call the new Callable @@ -215,7 +215,7 @@ class NotificationStatsLoggerTest : SysuiTestCase() { // GIVEN some visible Notifications are reported val (ranks, locations) = fakeNotificationMaps("key0", "key1") val callable = Callable { locations } - underTest.onNotificationListUpdated(callable, ranks) + underTest.onNotificationLocationsChanged(callable, ranks) runCurrent() clearInvocations(mockStatusBarService, mockNotificationListenerService) @@ -281,7 +281,7 @@ class NotificationStatsLoggerTest : SysuiTestCase() { } @Test - fun onNotificationExpanded_visibleLocation_expansionLogged() = + fun onNotificationExpansionChanged_whenExpandedInVisibleLocation_logsExpansion() = testScope.runTest { // WHEN a Notification is expanded underTest.onNotificationExpansionChanged( @@ -303,7 +303,33 @@ class NotificationStatsLoggerTest : SysuiTestCase() { } @Test - fun onNotificationExpanded_notVisibleLocation_nothingLogged() = + fun onNotificationExpansionChanged_whenCalledTwiceWithTheSameUpdate_doesNotDuplicateLogs() = + testScope.runTest { + // GIVEN a Notification is expanded + underTest.onNotificationExpansionChanged( + key = "key", + isExpanded = true, + location = ExpandableViewState.LOCATION_MAIN_AREA, + isUserAction = true + ) + runCurrent() + clearInvocations(mockStatusBarService) + + // WHEN the logger receives the same expansion update + underTest.onNotificationExpansionChanged( + key = "key", + isExpanded = true, + location = ExpandableViewState.LOCATION_MAIN_AREA, + isUserAction = true + ) + runCurrent() + + // THEN the Expand event is not reported again + verifyZeroInteractions(mockStatusBarService) + } + + @Test + fun onNotificationExpansionChanged_whenCalledForNotVisibleItem_nothingLogged() = testScope.runTest { // WHEN a NOT visible Notification is expanded underTest.onNotificationExpansionChanged( @@ -319,35 +345,73 @@ class NotificationStatsLoggerTest : SysuiTestCase() { } @Test - fun onNotificationExpanded_notVisibleLocation_becomesVisible_expansionLogged() = + fun onNotificationExpansionChanged_whenNotVisibleItemBecomesVisible_logsChanges() = testScope.runTest { // WHEN a NOT visible Notification is expanded underTest.onNotificationExpansionChanged( key = "key", isExpanded = true, location = ExpandableViewState.LOCATION_GONE, - isUserAction = true + isUserAction = false ) runCurrent() // AND it becomes visible val (ranks, locations) = fakeNotificationMaps("key") val callable = Callable { locations } - underTest.onNotificationListUpdated(callable, ranks) + underTest.onNotificationLocationsChanged(callable, ranks) runCurrent() // THEN the Expand event is reported verify(mockStatusBarService) .onNotificationExpansionChanged( /* key = */ "key", - /* userAction = */ true, + /* userAction = */ false, + /* expanded = */ true, + NotificationVisibility.NotificationLocation.LOCATION_MAIN_AREA.ordinal + ) + } + + @Test + fun onNotificationExpansionChanged_whenUpdatedItemBecomesVisible_logsChanges() = + testScope.runTest { + // GIVEN a NOT visible Notification is expanded + underTest.onNotificationExpansionChanged( + key = "key", + isExpanded = true, + location = ExpandableViewState.LOCATION_GONE, + isUserAction = false + ) + runCurrent() + // AND we open the shade, so we log its events + val (ranks, locations) = fakeNotificationMaps("key") + val callable = Callable { locations } + underTest.onNotificationLocationsChanged(callable, ranks) + runCurrent() + // AND we close the shade, so it is NOT visible + val emptyCallable = Callable { emptyMap<String, Int>() } + underTest.onNotificationLocationsChanged(emptyCallable, ranks) + runCurrent() + clearInvocations(mockStatusBarService) // clear the previous expand log + + // WHEN it receives an update + underTest.onNotificationUpdated("key") + // AND it becomes visible again + underTest.onNotificationLocationsChanged(callable, ranks) + runCurrent() + + // THEN we log its expand event again + verify(mockStatusBarService) + .onNotificationExpansionChanged( + /* key = */ "key", + /* userAction = */ false, /* expanded = */ true, NotificationVisibility.NotificationLocation.LOCATION_MAIN_AREA.ordinal ) } @Test - fun onNotificationCollapsed_isFirstInteraction_nothingLogged() = + fun onNotificationExpansionChanged_whenCollapsedForTheFirstTime_nothingLogged() = testScope.runTest { // WHEN a Notification is collapsed, and it is the first interaction underTest.onNotificationExpansionChanged( @@ -364,7 +428,7 @@ class NotificationStatsLoggerTest : SysuiTestCase() { } @Test - fun onNotificationExpandedAndCollapsed_expansionChangesLogged() = + fun onNotificationExpansionChanged_receivesMultipleUpdates_logsChanges() = testScope.runTest { // GIVEN a Notification is expanded underTest.onNotificationExpansionChanged( @@ -403,6 +467,60 @@ class NotificationStatsLoggerTest : SysuiTestCase() { ) } + @Test + fun onNotificationUpdated_clearsTrackedExpansionChanges() = + testScope.runTest { + // GIVEN some notification updates are posted + underTest.onNotificationExpansionChanged( + key = "key1", + isExpanded = true, + location = ExpandableViewState.LOCATION_MAIN_AREA, + isUserAction = true + ) + runCurrent() + underTest.onNotificationExpansionChanged( + key = "key2", + isExpanded = true, + location = ExpandableViewState.LOCATION_MAIN_AREA, + isUserAction = true + ) + runCurrent() + clearInvocations(mockStatusBarService) + + // WHEN a Notification is updated + underTest.onNotificationUpdated("key1") + + // THEN the tracked expansion changes are updated + assertThat(underTest.lastReportedExpansionValues.keys).containsExactly("key2") + } + + @Test + fun onNotificationRemoved_clearsTrackedExpansionChanges() = + testScope.runTest { + // GIVEN some notification updates are posted + underTest.onNotificationExpansionChanged( + key = "key1", + isExpanded = true, + location = ExpandableViewState.LOCATION_MAIN_AREA, + isUserAction = true + ) + runCurrent() + underTest.onNotificationExpansionChanged( + key = "key2", + isExpanded = true, + location = ExpandableViewState.LOCATION_MAIN_AREA, + isUserAction = true + ) + runCurrent() + clearInvocations(mockStatusBarService) + + // WHEN a Notification is removed + underTest.onNotificationRemoved("key1") + + // THEN it is removed from the tracked expansion changes + assertThat(underTest.lastReportedExpansionValues.keys).doesNotContain("key1") + } + private fun fakeNotificationMaps( vararg keys: String ): Pair<Map<String, Int>, Map<String, Int>> { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt index a824bc4f803f..06298b78ae57 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt @@ -25,6 +25,9 @@ import com.android.systemui.Flags.FLAG_CENTRALIZED_STATUS_BAR_DIMENS_REFACTOR import com.android.systemui.SysuiTestCase import com.android.systemui.common.shared.model.NotificationContainerBounds import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository +import com.android.systemui.communal.domain.interactor.communalInteractor +import com.android.systemui.communal.shared.model.CommunalSceneKey +import com.android.systemui.communal.shared.model.ObservableCommunalTransitionState import com.android.systemui.coroutines.collectLastValue import com.android.systemui.flags.Flags import com.android.systemui.flags.fakeFeatureFlagsClassic @@ -33,20 +36,19 @@ import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepos import com.android.systemui.keyguard.domain.interactor.keyguardInteractor import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.shared.model.StatusBarState -import com.android.systemui.keyguard.shared.model.StatusBarState.SHADE_LOCKED import com.android.systemui.keyguard.shared.model.TransitionState import com.android.systemui.keyguard.shared.model.TransitionStep import com.android.systemui.keyguard.ui.viewmodel.keyguardRootViewModel import com.android.systemui.kosmos.testScope import com.android.systemui.res.R import com.android.systemui.shade.data.repository.shadeRepository -import com.android.systemui.shade.largeScreenHeaderHelper import com.android.systemui.shade.mockLargeScreenHeaderHelper import com.android.systemui.statusbar.notification.stack.domain.interactor.sharedNotificationContainerInteractor import com.android.systemui.testKosmos import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest @@ -68,6 +70,7 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() { val keyguardInteractor = kosmos.keyguardInteractor val keyguardRootViewModel = kosmos.keyguardRootViewModel val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository + val communalInteractor = kosmos.communalInteractor val shadeRepository = kosmos.shadeRepository val sharedNotificationContainerInteractor = kosmos.sharedNotificationContainerInteractor val largeScreenHeaderHelper = kosmos.mockLargeScreenHeaderHelper @@ -214,6 +217,61 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() { } @Test + fun glanceableHubAlpha() = + testScope.runTest { + val alpha by collectLastValue(underTest.glanceableHubAlpha) + + // Start on lockscreen + showLockscreen() + assertThat(alpha).isEqualTo(1f) + + // Start transitioning to glanceable hub + val progress = 0.6f + keyguardTransitionRepository.sendTransitionStep( + TransitionStep( + transitionState = TransitionState.STARTED, + from = KeyguardState.LOCKSCREEN, + to = KeyguardState.GLANCEABLE_HUB, + value = 0f, + ) + ) + runCurrent() + keyguardTransitionRepository.sendTransitionStep( + TransitionStep( + transitionState = TransitionState.RUNNING, + from = KeyguardState.LOCKSCREEN, + to = KeyguardState.GLANCEABLE_HUB, + value = progress, + ) + ) + runCurrent() + // Expected alpha is inverse of progress as notifications are fading away + assertThat(alpha).isEqualTo(1 - progress) + + // Finish transition to glanceable hub + keyguardTransitionRepository.sendTransitionStep( + TransitionStep( + transitionState = TransitionState.FINISHED, + from = KeyguardState.LOCKSCREEN, + to = KeyguardState.GLANCEABLE_HUB, + value = 1f, + ) + ) + val idleTransitionState = + MutableStateFlow<ObservableCommunalTransitionState>( + ObservableCommunalTransitionState.Idle(CommunalSceneKey.Communal) + ) + communalInteractor.setTransitionState(idleTransitionState) + runCurrent() + assertThat(alpha).isEqualTo(0f) + + // While state is GLANCEABLE_HUB, verify alpha is restored to full if glanceable hub is + // not fully visible. + shadeRepository.setLockscreenShadeExpansion(0.1f) + assertThat(alpha).isEqualTo(1f) + } + + @Test fun validateMarginTop() = testScope.runTest { overrideResource(R.bool.config_use_large_screen_shade_header, false) @@ -302,6 +360,43 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() { } @Test + fun isOnGlanceableHubWithoutShade() = + testScope.runTest { + val isOnGlanceableHubWithoutShade by + collectLastValue(underTest.isOnGlanceableHubWithoutShade) + + // Start on lockscreen + showLockscreen() + assertThat(isOnGlanceableHubWithoutShade).isFalse() + + // Move to glanceable hub + val idleTransitionState = + MutableStateFlow<ObservableCommunalTransitionState>( + ObservableCommunalTransitionState.Idle(CommunalSceneKey.Communal) + ) + communalInteractor.setTransitionState(idleTransitionState) + runCurrent() + assertThat(isOnGlanceableHubWithoutShade).isTrue() + + // While state is GLANCEABLE_HUB, validate variations of both shade and qs expansion + shadeRepository.setLockscreenShadeExpansion(0.1f) + shadeRepository.setQsExpansion(0f) + assertThat(isOnGlanceableHubWithoutShade).isFalse() + + shadeRepository.setLockscreenShadeExpansion(0.1f) + shadeRepository.setQsExpansion(0.1f) + assertThat(isOnGlanceableHubWithoutShade).isFalse() + + shadeRepository.setLockscreenShadeExpansion(0f) + shadeRepository.setQsExpansion(0.1f) + assertThat(isOnGlanceableHubWithoutShade).isFalse() + + shadeRepository.setLockscreenShadeExpansion(0f) + shadeRepository.setQsExpansion(0f) + assertThat(isOnGlanceableHubWithoutShade).isTrue() + } + + @Test fun boundsOnLockscreenNotInSplitShade() = testScope.runTest { val bounds by collectLastValue(underTest.bounds) 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 4827c92ce452..b3a47d77a307 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 @@ -48,7 +48,6 @@ import android.content.Context; import android.content.res.ColorStateList; import android.content.res.TypedArray; import android.graphics.Color; -import android.os.Handler; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.util.MathUtils; @@ -66,6 +65,7 @@ import com.android.systemui.animation.ShadeInterpolation; import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants; import com.android.systemui.dock.DockManager; import com.android.systemui.keyguard.KeyguardUnlockAnimationController; +import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor; import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor; import com.android.systemui.keyguard.shared.model.KeyguardState; import com.android.systemui.keyguard.shared.model.TransitionState; @@ -134,7 +134,7 @@ public class ScrimControllerTest extends SysuiTestCase { @Mock private AlarmManager mAlarmManager; @Mock private DozeParameters mDozeParameters; @Mock private LightBarController mLightBarController; - @Mock private DelayedWakeLock.Builder mDelayedWakeLockBuilder; + @Mock private DelayedWakeLock.Factory mDelayedWakeLockFactory; @Mock private DelayedWakeLock mWakeLock; @Mock private KeyguardStateController mKeyguardStateController; @Mock private KeyguardUpdateMonitor mKeyguardUpdateMonitor; @@ -145,6 +145,7 @@ public class ScrimControllerTest extends SysuiTestCase { @Mock private AlternateBouncerToGoneTransitionViewModel mAlternateBouncerToGoneTransitionViewModel; @Mock private KeyguardTransitionInteractor mKeyguardTransitionInteractor; + @Mock private KeyguardInteractor mKeyguardInteractor; private final FakeWallpaperRepository mWallpaperRepository = new FakeWallpaperRepository(); @Mock private CoroutineDispatcher mMainDispatcher; @Mock private TypedArray mMockTypedArray; @@ -260,11 +261,7 @@ public class ScrimControllerTest extends SysuiTestCase { }).when(mLightBarController).setScrimState( any(ScrimState.class), anyFloat(), any(GradientColors.class)); - when(mDelayedWakeLockBuilder.setHandler(any(Handler.class))) - .thenReturn(mDelayedWakeLockBuilder); - when(mDelayedWakeLockBuilder.setTag(any(String.class))) - .thenReturn(mDelayedWakeLockBuilder); - when(mDelayedWakeLockBuilder.build()).thenReturn(mWakeLock); + when(mDelayedWakeLockFactory.create(any(String.class))).thenReturn(mWakeLock); when(mDockManager.isDocked()).thenReturn(false); when(mKeyguardTransitionInteractor.transition(any(), any())) @@ -279,7 +276,7 @@ public class ScrimControllerTest extends SysuiTestCase { mDozeParameters, mAlarmManager, mKeyguardStateController, - mDelayedWakeLockBuilder, + mDelayedWakeLockFactory, new FakeHandler(mLooper.getLooper()), mKeyguardUpdateMonitor, mDockManager, @@ -292,6 +289,7 @@ public class ScrimControllerTest extends SysuiTestCase { mPrimaryBouncerToGoneTransitionViewModel, mAlternateBouncerToGoneTransitionViewModel, mKeyguardTransitionInteractor, + mKeyguardInteractor, mWallpaperRepository, mMainDispatcher, mLinearLargeScreenShadeInterpolator); @@ -987,7 +985,7 @@ public class ScrimControllerTest extends SysuiTestCase { mDozeParameters, mAlarmManager, mKeyguardStateController, - mDelayedWakeLockBuilder, + mDelayedWakeLockFactory, new FakeHandler(mLooper.getLooper()), mKeyguardUpdateMonitor, mDockManager, @@ -1000,6 +998,7 @@ public class ScrimControllerTest extends SysuiTestCase { mPrimaryBouncerToGoneTransitionViewModel, mAlternateBouncerToGoneTransitionViewModel, mKeyguardTransitionInteractor, + mKeyguardInteractor, mWallpaperRepository, mMainDispatcher, mLinearLargeScreenShadeInterpolator); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt index 1f8cc54211e6..6785de930849 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt @@ -168,6 +168,7 @@ internal class DemoMobileConnectionParameterizedTest(private val testCase: TestC assertThat(conn.carrierName.value) .isEqualTo(NetworkNameModel.SubscriptionDerived("${model.name} ${model.subId}")) assertThat(conn.hasPrioritizedNetworkCapabilities.value).isEqualTo(model.slice) + assertThat(conn.isNonTerrestrial.value).isEqualTo(model.ntn) // TODO(b/261029387): check these once we start handling them assertThat(conn.isEmergencyOnly.value).isFalse() @@ -194,6 +195,7 @@ internal class DemoMobileConnectionParameterizedTest(private val testCase: TestC val roaming: Boolean, val name: String, val slice: Boolean, + val ntn: Boolean, ) { override fun toString(): String { return "INPUT(level=$level, " + @@ -205,7 +207,8 @@ internal class DemoMobileConnectionParameterizedTest(private val testCase: TestC "carrierNetworkChange=$carrierNetworkChange, " + "roaming=$roaming, " + "name=$name," + - "slice=$slice)" + "slice=$slice" + + "ntn=$ntn)" } // Convenience for iterating test data and creating new cases @@ -220,6 +223,7 @@ internal class DemoMobileConnectionParameterizedTest(private val testCase: TestC roaming: Boolean? = null, name: String? = null, slice: Boolean? = null, + ntn: Boolean? = null, ): TestCase = TestCase( level = level ?: this.level, @@ -232,6 +236,7 @@ internal class DemoMobileConnectionParameterizedTest(private val testCase: TestC roaming = roaming ?: this.roaming, name = name ?: this.name, slice = slice ?: this.slice, + ntn = ntn ?: this.ntn, ) } @@ -262,6 +267,7 @@ internal class DemoMobileConnectionParameterizedTest(private val testCase: TestC private val roaming = listOf(false, true) private val names = listOf("name 1", "name 2") private val slice = listOf(false, true) + private val ntn = listOf(false, true) @Parameters(name = "{0}") @JvmStatic fun data() = testData() @@ -300,6 +306,7 @@ internal class DemoMobileConnectionParameterizedTest(private val testCase: TestC roaming.first(), names.first(), slice.first(), + ntn.first(), ) val tail = @@ -312,7 +319,8 @@ internal class DemoMobileConnectionParameterizedTest(private val testCase: TestC carrierNetworkChange.map { baseCase.modifiedBy(carrierNetworkChange = it) }, roaming.map { baseCase.modifiedBy(roaming = it) }, names.map { baseCase.modifiedBy(name = it) }, - slice.map { baseCase.modifiedBy(slice = it) } + slice.map { baseCase.modifiedBy(slice = it) }, + ntn.map { baseCase.modifiedBy(ntn = it) } ) .flatten() diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt index 03814bdfa430..b958f35c0e53 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt @@ -579,6 +579,7 @@ class DemoMobileConnectionsRepositoryTest : SysuiTestCase() { assertThat(conn.carrierName.value) .isEqualTo(NetworkNameModel.SubscriptionDerived("${model.name} ${model.subId}")) assertThat(conn.hasPrioritizedNetworkCapabilities.value).isEqualTo(model.slice) + assertThat(conn.isNonTerrestrial.value).isEqualTo(model.ntn) // TODO(b/261029387) check these once we start handling them assertThat(conn.isEmergencyOnly.value).isFalse() diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt index 9d6f3156f83e..98556514f8ec 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt @@ -21,6 +21,7 @@ import android.content.Context import android.content.Intent import android.net.ConnectivityManager import android.net.ConnectivityManager.NetworkCallback +import android.platform.test.annotations.EnableFlags import android.telephony.AccessNetworkConstants.TRANSPORT_TYPE_WLAN import android.telephony.AccessNetworkConstants.TRANSPORT_TYPE_WWAN import android.telephony.CarrierConfigManager.KEY_INFLATE_SIGNAL_STRENGTH_BOOL @@ -963,6 +964,31 @@ class MobileConnectionRepositoryTest : SysuiTestCase() { } @Test + @EnableFlags(com.android.internal.telephony.flags.Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG) + fun isNonTerrestrial_updatesFromServiceState() = + testScope.runTest { + val latest by collectLastValue(underTest.isNonTerrestrial) + + // Lambda makes it a little clearer what we are testing IMO + val serviceStateCreator = { ntn: Boolean -> + mock<ServiceState>().also { + whenever(it.isUsingNonTerrestrialNetwork).thenReturn(ntn) + } + } + + // Starts out false + assertThat(latest).isFalse() + + getTelephonyCallbackForType<ServiceStateListener>() + .onServiceStateChanged(serviceStateCreator(true)) + assertThat(latest).isTrue() + + getTelephonyCallbackForType<ServiceStateListener>() + .onServiceStateChanged(serviceStateCreator(false)) + assertThat(latest).isFalse() + } + + @Test fun numberOfLevels_usesCarrierConfig() = testScope.runTest { var latest: Int? = null diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImplTest.kt index 02e6fd5a9d6e..0e0d4897d667 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImplTest.kt @@ -35,6 +35,7 @@ import android.telephony.satellite.SatelliteModemStateCallback import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.log.core.FakeLogBuffer import com.android.systemui.statusbar.pipeline.satellite.data.prod.DeviceBasedSatelliteRepositoryImpl.Companion.MIN_UPTIME import com.android.systemui.statusbar.pipeline.satellite.data.prod.DeviceBasedSatelliteRepositoryImpl.Companion.POLLING_INTERVAL_MS import com.android.systemui.statusbar.pipeline.satellite.shared.model.SatelliteConnectionState @@ -87,6 +88,7 @@ class DeviceBasedSatelliteRepositoryImplTest : SysuiTestCase() { Optional.empty(), dispatcher, testScope.backgroundScope, + FakeLogBuffer.Factory.create(), systemClock, ) @@ -100,6 +102,45 @@ class DeviceBasedSatelliteRepositoryImplTest : SysuiTestCase() { } @Test + fun satelliteManagerThrows_checkSupportDoesNotCrash() = + testScope.runTest { + whenever(satelliteManager.requestIsSatelliteSupported(any(), any())) + .thenThrow(IllegalStateException()) + + systemClock.setUptimeMillis(Process.getStartUptimeMillis() + MIN_UPTIME) + + underTest = + DeviceBasedSatelliteRepositoryImpl( + Optional.of(satelliteManager), + dispatcher, + testScope.backgroundScope, + FakeLogBuffer.Factory.create(), + systemClock, + ) + + runCurrent() + + // Creating the repo does not crash, and we consider the feature not to be supported + assertThat(underTest.satelliteSupport.value).isEqualTo(SatelliteSupport.NotSupported) + } + + @Test + fun satelliteManagerThrows_doesNotCrash() = + testScope.runTest { + setupDefaultRepo() + + whenever(satelliteManager.registerForNtnSignalStrengthChanged(any(), any())) + .thenThrow(SatelliteException(13)) + + val conn by collectLastValue(underTest.connectionState) + val strength by collectLastValue(underTest.signalStrength) + + // Flows have not emitted, we haven't crashed + assertThat(conn).isNull() + assertThat(strength).isNull() + } + + @Test fun connectionState_mapsFromSatelliteModemState() = testScope.runTest { setupDefaultRepo() @@ -380,6 +421,7 @@ class DeviceBasedSatelliteRepositoryImplTest : SysuiTestCase() { if (satMan != null) Optional.of(satMan) else Optional.empty(), dispatcher, testScope.backgroundScope, + FakeLogBuffer.Factory.create(), systemClock, ) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModelTest.kt new file mode 100644 index 000000000000..21c038ad476d --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModelTest.kt @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.pipeline.satellite.ui.viewmodel + +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.common.shared.model.Icon +import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.FakeMobileIconsInteractor +import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy +import com.android.systemui.statusbar.pipeline.satellite.data.prod.FakeDeviceBasedSatelliteRepository +import com.android.systemui.statusbar.pipeline.satellite.domain.interactor.DeviceBasedSatelliteInteractor +import com.android.systemui.util.mockito.mock +import com.google.common.truth.Truth.assertThat +import kotlin.test.Test +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.runTest +import org.junit.Before +import org.mockito.MockitoAnnotations + +@SmallTest +class DeviceBasedSatelliteViewModelTest : SysuiTestCase() { + private lateinit var underTest: DeviceBasedSatelliteViewModel + private lateinit var interactor: DeviceBasedSatelliteInteractor + + private val repo = FakeDeviceBasedSatelliteRepository() + private val mobileIconsInteractor = FakeMobileIconsInteractor(FakeMobileMappingsProxy(), mock()) + + private val testScope = TestScope() + + @Before + fun setUp() { + MockitoAnnotations.initMocks(this) + + interactor = + DeviceBasedSatelliteInteractor( + repo, + mobileIconsInteractor, + testScope.backgroundScope, + ) + + underTest = + DeviceBasedSatelliteViewModel( + interactor, + testScope.backgroundScope, + ) + } + + @Test + fun icon_nullWhenShouldNotShow_satelliteNotAllowed() = + testScope.runTest { + val latest by collectLastValue(underTest.icon) + + // GIVEN satellite is not allowed + repo.isSatelliteAllowedForCurrentLocation.value = false + + // GIVEN all icons are OOS + val i1 = mobileIconsInteractor.getMobileConnectionInteractorForSubId(1) + i1.isInService.value = false + + // THEN icon is null because we should not be showing it + assertThat(latest).isNull() + } + + @Test + fun icon_nullWhenShouldNotShow_notAllOos() = + testScope.runTest { + val latest by collectLastValue(underTest.icon) + + // GIVEN satellite is allowed + repo.isSatelliteAllowedForCurrentLocation.value = true + + // GIVEN all icons are not OOS + val i1 = mobileIconsInteractor.getMobileConnectionInteractorForSubId(1) + i1.isInService.value = true + + // THEN icon is null because we have service + assertThat(latest).isNull() + } + + @Test + fun icon_satelliteIsOff() = + testScope.runTest { + val latest by collectLastValue(underTest.icon) + + // GIVEN satellite is allowed + repo.isSatelliteAllowedForCurrentLocation.value = true + + // GIVEN all icons are OOS + val i1 = mobileIconsInteractor.getMobileConnectionInteractorForSubId(1) + i1.isInService.value = false + + // THEN icon is null because we have service + assertThat(latest).isInstanceOf(Icon::class.java) + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/view/SingleBindableStatusBarIconViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/view/SingleBindableStatusBarIconViewTest.kt new file mode 100644 index 000000000000..ca9df57e8798 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/view/SingleBindableStatusBarIconViewTest.kt @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.pipeline.shared.ui.view + +import android.graphics.Rect +import android.testing.AndroidTestingRunner +import android.testing.TestableLooper +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.statusbar.StatusBarIconView +import com.google.common.truth.Truth.assertThat +import org.junit.Test +import org.junit.runner.RunWith + +/** + * Being a simple subclass of [ModernStatusBarView], use the same basic test cases to verify the + * root behavior, and add testing for the new [SingleBindableStatusBarIconView.withDefaultBinding] + * method. + */ +@SmallTest +@RunWith(AndroidTestingRunner::class) +@TestableLooper.RunWithLooper(setAsMainLooper = true) +class SingleBindableStatusBarIconViewTest : SysuiTestCase() { + private lateinit var binding: SingleBindableStatusBarIconViewBinding + + // Visibility is outsourced to view-models. This simulates it + private var isVisible = true + private var visibilityFn: () -> Boolean = { isVisible } + + @Test + fun initView_hasCorrectSlot() { + val view = createAndInitView() + + assertThat(view.slot).isEqualTo(SLOT_NAME) + } + + @Test + fun getVisibleState_icon_returnsIcon() { + val view = createAndInitView() + + view.setVisibleState(StatusBarIconView.STATE_ICON, /* animate= */ false) + + assertThat(view.visibleState).isEqualTo(StatusBarIconView.STATE_ICON) + } + + @Test + fun getVisibleState_dot_returnsDot() { + val view = createAndInitView() + + view.setVisibleState(StatusBarIconView.STATE_DOT, /* animate= */ false) + + assertThat(view.visibleState).isEqualTo(StatusBarIconView.STATE_DOT) + } + + @Test + fun getVisibleState_hidden_returnsHidden() { + val view = createAndInitView() + + view.setVisibleState(StatusBarIconView.STATE_HIDDEN, /* animate= */ false) + + assertThat(view.visibleState).isEqualTo(StatusBarIconView.STATE_HIDDEN) + } + + @Test + fun onDarkChanged_bindingReceivesIconAndDecorTint() { + val view = createAndInitView() + + view.onDarkChangedWithContrast(arrayListOf(), 0x12345678, 0x12344321) + + assertThat(binding.iconTint).isEqualTo(0x12345678) + assertThat(binding.decorTint).isEqualTo(0x12345678) + } + + @Test + fun setStaticDrawableColor_bindingReceivesIconTint() { + val view = createAndInitView() + + view.setStaticDrawableColor(0x12345678, 0x12344321) + + assertThat(binding.iconTint).isEqualTo(0x12345678) + } + + @Test + fun setDecorColor_bindingReceivesDecorColor() { + val view = createAndInitView() + + view.setDecorColor(0x23456789) + + assertThat(binding.decorTint).isEqualTo(0x23456789) + } + + @Test + fun isIconVisible_usesBinding_true() { + val view = createAndInitView() + + isVisible = true + + assertThat(view.isIconVisible).isEqualTo(true) + } + + @Test + fun isIconVisible_usesBinding_false() { + val view = createAndInitView() + + isVisible = false + + assertThat(view.isIconVisible).isEqualTo(false) + } + + @Test + fun getDrawingRect_takesTranslationIntoAccount() { + val view = createAndInitView() + + view.translationX = 50f + view.translationY = 60f + + val drawingRect = Rect() + view.getDrawingRect(drawingRect) + + assertThat(drawingRect.left).isEqualTo(view.left + 50) + assertThat(drawingRect.right).isEqualTo(view.right + 50) + assertThat(drawingRect.top).isEqualTo(view.top + 60) + assertThat(drawingRect.bottom).isEqualTo(view.bottom + 60) + } + + private fun createAndInitView(): SingleBindableStatusBarIconView { + val view = SingleBindableStatusBarIconView.createView(context) + binding = SingleBindableStatusBarIconView.withDefaultBinding(view, visibilityFn) {} + view.initView(SLOT_NAME) { binding } + return view + } + + companion object { + private const val SLOT_NAME = "test_slot" + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerTest.kt new file mode 100644 index 000000000000..cd5d5ed0d08e --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SensitiveNotificationProtectionControllerTest.kt @@ -0,0 +1,231 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.policy + +import android.app.Notification +import android.media.projection.MediaProjectionInfo +import android.media.projection.MediaProjectionManager +import android.os.Handler +import android.service.notification.StatusBarNotification +import android.testing.AndroidTestingRunner +import androidx.test.filters.SmallTest +import com.android.systemui.Flags +import com.android.systemui.SysuiTestCase +import com.android.systemui.statusbar.notification.collection.NotificationEntry +import org.junit.Assert.assertFalse +import org.junit.Assert.assertNotNull +import org.junit.Assert.assertTrue +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.ArgumentCaptor +import org.mockito.ArgumentMatchers.any +import org.mockito.Captor +import org.mockito.Mock +import org.mockito.Mockito.mock +import org.mockito.Mockito.reset +import org.mockito.Mockito.times +import org.mockito.Mockito.verify +import org.mockito.Mockito.verifyNoMoreInteractions +import org.mockito.Mockito.verifyZeroInteractions +import org.mockito.Mockito.`when` +import org.mockito.MockitoAnnotations + +@SmallTest +@RunWith(AndroidTestingRunner::class) +class SensitiveNotificationProtectionControllerTest : SysuiTestCase() { + @Mock private lateinit var handler: Handler + + @Mock private lateinit var mediaProjectionManager: MediaProjectionManager + + @Mock private lateinit var mediaProjectionInfo: MediaProjectionInfo + + @Mock private lateinit var listener1: Runnable + @Mock private lateinit var listener2: Runnable + @Mock private lateinit var listener3: Runnable + + @Captor + private lateinit var mediaProjectionCallbackCaptor: + ArgumentCaptor<MediaProjectionManager.Callback> + + private lateinit var controller: SensitiveNotificationProtectionControllerImpl + + @Before + fun setUp() { + MockitoAnnotations.initMocks(this) + mSetFlagsRule.enableFlags(Flags.FLAG_SCREENSHARE_NOTIFICATION_HIDING) + + controller = SensitiveNotificationProtectionControllerImpl(mediaProjectionManager, handler) + + // Obtain useful MediaProjectionCallback + verify(mediaProjectionManager).addCallback(mediaProjectionCallbackCaptor.capture(), any()) + } + + @Test + fun init_flagEnabled_registerMediaProjectionManagerCallback() { + assertNotNull(mediaProjectionCallbackCaptor.value) + } + + @Test + fun init_flagDisabled_noRegisterMediaProjectionManagerCallback() { + mSetFlagsRule.disableFlags(Flags.FLAG_SCREENSHARE_NOTIFICATION_HIDING) + reset(mediaProjectionManager) + + controller = SensitiveNotificationProtectionControllerImpl(mediaProjectionManager, handler) + + verifyZeroInteractions(mediaProjectionManager) + } + + @Test + fun registerSensitiveStateListener_singleListener() { + controller.registerSensitiveStateListener(listener1) + + mediaProjectionCallbackCaptor.value.onStart(mediaProjectionInfo) + mediaProjectionCallbackCaptor.value.onStop(mediaProjectionInfo) + + verify(listener1, times(2)).run() + } + + @Test + fun registerSensitiveStateListener_multipleListeners() { + controller.registerSensitiveStateListener(listener1) + controller.registerSensitiveStateListener(listener2) + + mediaProjectionCallbackCaptor.value.onStart(mediaProjectionInfo) + mediaProjectionCallbackCaptor.value.onStop(mediaProjectionInfo) + + verify(listener1, times(2)).run() + verify(listener2, times(2)).run() + } + + @Test + fun registerSensitiveStateListener_afterProjectionActive() { + mediaProjectionCallbackCaptor.value.onStart(mediaProjectionInfo) + + controller.registerSensitiveStateListener(listener1) + verifyZeroInteractions(listener1) + + mediaProjectionCallbackCaptor.value.onStop(mediaProjectionInfo) + + verify(listener1).run() + } + + @Test + fun unregisterSensitiveStateListener_singleListener() { + controller.registerSensitiveStateListener(listener1) + + mediaProjectionCallbackCaptor.value.onStart(mediaProjectionInfo) + mediaProjectionCallbackCaptor.value.onStop(mediaProjectionInfo) + + verify(listener1, times(2)).run() + + controller.unregisterSensitiveStateListener(listener1) + + mediaProjectionCallbackCaptor.value.onStart(mediaProjectionInfo) + mediaProjectionCallbackCaptor.value.onStop(mediaProjectionInfo) + + verifyNoMoreInteractions(listener1) + } + + @Test + fun unregisterSensitiveStateListener_multipleListeners() { + controller.registerSensitiveStateListener(listener1) + controller.registerSensitiveStateListener(listener2) + controller.registerSensitiveStateListener(listener3) + + mediaProjectionCallbackCaptor.value.onStart(mediaProjectionInfo) + mediaProjectionCallbackCaptor.value.onStop(mediaProjectionInfo) + + verify(listener1, times(2)).run() + verify(listener2, times(2)).run() + verify(listener3, times(2)).run() + + controller.unregisterSensitiveStateListener(listener1) + controller.unregisterSensitiveStateListener(listener2) + + mediaProjectionCallbackCaptor.value.onStart(mediaProjectionInfo) + mediaProjectionCallbackCaptor.value.onStop(mediaProjectionInfo) + + verifyNoMoreInteractions(listener1) + verifyNoMoreInteractions(listener2) + verify(listener3, times(4)).run() + } + + @Test + fun isSensitiveStateActive_projectionInactive_false() { + assertFalse(controller.isSensitiveStateActive) + } + + @Test + fun isSensitiveStateActive_projectionActive_true() { + mediaProjectionCallbackCaptor.value.onStart(mediaProjectionInfo) + + assertTrue(controller.isSensitiveStateActive) + } + + @Test + fun isSensitiveStateActive_projectionInactiveAfterActive_false() { + mediaProjectionCallbackCaptor.value.onStart(mediaProjectionInfo) + mediaProjectionCallbackCaptor.value.onStop(mediaProjectionInfo) + + assertFalse(controller.isSensitiveStateActive) + } + + @Test + fun isSensitiveStateActive_projectionActiveAfterInactive_true() { + mediaProjectionCallbackCaptor.value.onStart(mediaProjectionInfo) + mediaProjectionCallbackCaptor.value.onStop(mediaProjectionInfo) + mediaProjectionCallbackCaptor.value.onStart(mediaProjectionInfo) + + assertTrue(controller.isSensitiveStateActive) + } + + @Test + fun shouldProtectNotification_projectionInactive_false() { + val notificationEntry = mock(NotificationEntry::class.java) + + assertFalse(controller.shouldProtectNotification(notificationEntry)) + } + + @Test + fun shouldProtectNotification_projectionActive_fgsNotification_false() { + mediaProjectionCallbackCaptor.value.onStart(mediaProjectionInfo) + + val notificationEntry = mock(NotificationEntry::class.java) + val sbn = mock(StatusBarNotification::class.java) + val notification = mock(Notification::class.java) + `when`(notificationEntry.sbn).thenReturn(sbn) + `when`(sbn.notification).thenReturn(notification) + `when`(notification.isFgsOrUij).thenReturn(true) + + assertFalse(controller.shouldProtectNotification(notificationEntry)) + } + + @Test + fun shouldProtectNotification_projectionActive_notFgsNotification_true() { + mediaProjectionCallbackCaptor.value.onStart(mediaProjectionInfo) + + val notificationEntry = mock(NotificationEntry::class.java) + val sbn = mock(StatusBarNotification::class.java) + val notification = mock(Notification::class.java) + `when`(notificationEntry.sbn).thenReturn(sbn) + `when`(sbn.notification).thenReturn(notification) + `when`(notification.isFgsOrUij).thenReturn(false) + + assertTrue(controller.shouldProtectNotification(notificationEntry)) + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java index 8c823b2376c3..d839da1d6e1b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java @@ -32,6 +32,7 @@ import static junit.framework.Assert.assertTrue; import static org.junit.Assume.assumeNotNull; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; @@ -63,6 +64,7 @@ import androidx.test.filters.SmallTest; import com.android.internal.jank.InteractionJankMonitor; import com.android.internal.logging.testing.UiEventLoggerFake; +import com.android.keyguard.TestScopeProvider; import com.android.systemui.Prefs; import com.android.systemui.SysuiTestCase; import com.android.systemui.animation.AnimatorTestRule; @@ -72,6 +74,7 @@ import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.VolumeDialogController; import com.android.systemui.plugins.VolumeDialogController.State; import com.android.systemui.res.R; +import com.android.systemui.statusbar.VibratorHelper; import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.DevicePostureController; @@ -79,6 +82,7 @@ import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.FakeConfigurationController; import com.android.systemui.util.settings.FakeSettings; import com.android.systemui.util.settings.SecureSettings; +import com.android.systemui.util.time.FakeSystemClock; import dagger.Lazy; @@ -97,6 +101,8 @@ import org.mockito.MockitoAnnotations; import java.util.Arrays; import java.util.function.Predicate; +import kotlinx.coroutines.Dispatchers; + @SmallTest @RunWith(AndroidTestingRunner.class) @TestableLooper.RunWithLooper(setAsMainLooper = true) @@ -138,7 +144,6 @@ public class VolumeDialogImplTest extends SysuiTestCase { DevicePostureController mPostureController; @Mock private Lazy<SecureSettings> mLazySecureSettings; - private final CsdWarningDialog.Factory mCsdWarningDialogFactory = new CsdWarningDialog.Factory() { @Override @@ -146,6 +151,8 @@ public class VolumeDialogImplTest extends SysuiTestCase { return mCsdWarningDialog; } }; + @Mock + private VibratorHelper mVibratorHelper; private int mLongestHideShowAnimationDuration = 250; private FakeSettings mSecureSettings; @@ -180,6 +187,8 @@ public class VolumeDialogImplTest extends SysuiTestCase { when(mLazySecureSettings.get()).thenReturn(mSecureSettings); + when(mVibratorHelper.getPrimitiveDurations(anyInt())).thenReturn(new int[]{0}); + mDialog = new VolumeDialogImpl( getContext(), mVolumeDialogController, @@ -195,7 +204,11 @@ public class VolumeDialogImplTest extends SysuiTestCase { mPostureController, mTestableLooper.getLooper(), mDumpManager, - mLazySecureSettings); + mLazySecureSettings, + mVibratorHelper, + Dispatchers.getUnconfined(), + TestScopeProvider.getTestScope(), + new FakeSystemClock()); mDialog.init(0, null); State state = createShellState(); mDialog.onStateChangedH(state); diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java index 589f7c23ea13..98f3ede850f4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java @@ -100,7 +100,6 @@ import com.android.systemui.colorextraction.SysuiColorExtractor; import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository; import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor; import com.android.systemui.communal.domain.interactor.CommunalInteractor; -import com.android.systemui.communal.domain.interactor.CommunalInteractorFactory; import com.android.systemui.deviceentry.domain.interactor.DeviceEntryUdfpsInteractor; import com.android.systemui.dump.DumpManager; import com.android.systemui.flags.FakeFeatureFlags; @@ -443,8 +442,7 @@ public class BubblesTest extends SysuiTestCase { () -> keyguardInteractor, () -> mFromLockscreenTransitionInteractor, () -> mFromPrimaryBouncerTransitionInteractor); - CommunalInteractor communalInteractor = - CommunalInteractorFactory.create().getCommunalInteractor(); + CommunalInteractor communalInteractor = mKosmos.getCommunalInteractor(); mFromLockscreenTransitionInteractor = new FromLockscreenTransitionInteractor( keyguardTransitionRepository, @@ -458,6 +456,7 @@ public class BubblesTest extends SysuiTestCase { powerInteractor, new GlanceableHubTransitions( mTestScope, + mKosmos.getTestDispatcher(), keyguardTransitionInteractor, keyguardTransitionRepository, communalInteractor @@ -479,6 +478,7 @@ public class BubblesTest extends SysuiTestCase { mKosmos.getTestDispatcher(), mKosmos.getTestDispatcher(), keyguardInteractor, + communalInteractor, featureFlags, mock(KeyguardSecurityModel.class), mSelectedUserInteractor, @@ -536,7 +536,8 @@ public class BubblesTest extends SysuiTestCase { mShadeWindowLogger, () -> mSelectedUserInteractor, mUserTracker, - mSceneContainerFlags + mSceneContainerFlags, + mKosmos::getCommunalInteractor ); mNotificationShadeWindowController.fetchWindowRootView(); mNotificationShadeWindowController.attach(); diff --git a/packages/SystemUI/tests/utils/src/android/animation/AnimatorTestRule.java b/packages/SystemUI/tests/utils/src/android/animation/AnimatorTestRule.java index b820ca612bfc..1afe56f27be7 100644 --- a/packages/SystemUI/tests/utils/src/android/animation/AnimatorTestRule.java +++ b/packages/SystemUI/tests/utils/src/android/animation/AnimatorTestRule.java @@ -22,6 +22,7 @@ import android.annotation.Nullable; import android.os.Looper; import android.os.SystemClock; import android.util.AndroidRuntimeException; +import android.util.Singleton; import android.view.Choreographer; import com.android.internal.util.Preconditions; @@ -67,7 +68,12 @@ import java.util.function.Consumer; public final class AnimatorTestRule implements TestRule { private final Object mLock = new Object(); - private final TestHandler mTestHandler = new TestHandler(); + private final Singleton<TestHandler> mTestHandler = new Singleton<>() { + @Override + protected TestHandler create() { + return new TestHandler(); + } + }; private final long mStartTime; private long mTotalTimeDelta = 0; @@ -95,16 +101,17 @@ public final class AnimatorTestRule implements TestRule { return new Statement() { @Override public void evaluate() throws Throwable { - AnimationHandler objAtStart = AnimationHandler.setTestHandler(mTestHandler); + final TestHandler testHandler = mTestHandler.get(); + AnimationHandler objAtStart = AnimationHandler.setTestHandler(testHandler); try { base.evaluate(); } finally { AnimationHandler objAtEnd = AnimationHandler.setTestHandler(objAtStart); - if (mTestHandler != objAtEnd) { + if (testHandler != objAtEnd) { // pass or fail, inner logic not restoring the handler needs to be reported. // noinspection ThrowFromFinallyBlock throw new IllegalStateException("Test handler was altered: expected=" - + mTestHandler + " actual=" + objAtEnd); + + testHandler + " actual=" + objAtEnd); } } } @@ -125,8 +132,9 @@ public final class AnimatorTestRule implements TestRule { public void initNewAnimators() { requireLooper("AnimationTestRule#initNewAnimators()"); long currentTime = getCurrentTime(); - List<AnimationFrameCallback> newCallbacks = new ArrayList<>(mTestHandler.mNewCallbacks); - mTestHandler.mNewCallbacks.clear(); + final TestHandler testHandler = mTestHandler.get(); + List<AnimationFrameCallback> newCallbacks = new ArrayList<>(testHandler.mNewCallbacks); + testHandler.mNewCallbacks.clear(); for (AnimationFrameCallback newCallback : newCallbacks) { newCallback.doAnimationFrame(currentTime); } @@ -158,9 +166,10 @@ public final class AnimatorTestRule implements TestRule { public void advanceTimeBy(long timeDelta, @Nullable Consumer<Long> preFrameAction) { Preconditions.checkArgumentNonnegative(timeDelta, "timeDelta must not be negative"); requireLooper("AnimationTestRule#advanceTimeBy(long)"); + final TestHandler testHandler = mTestHandler.get(); if (timeDelta == 0) { // If time is not being advanced, all animators will get a tick; don't double tick these - mTestHandler.mNewCallbacks.clear(); + testHandler.mNewCallbacks.clear(); } else { // before advancing time, start new animators with the current time initNewAnimators(); @@ -172,10 +181,10 @@ public final class AnimatorTestRule implements TestRule { if (preFrameAction != null) { preFrameAction.accept(timeDelta); // After letting other code run, clear any new callbacks to avoid double-ticking them - mTestHandler.mNewCallbacks.clear(); + testHandler.mNewCallbacks.clear(); } // produce a frame - mTestHandler.doFrame(); + testHandler.doFrame(); } /** diff --git a/packages/SystemUI/tests/utils/src/android/app/KeyguardManagerKosmos.kt b/packages/SystemUI/tests/utils/src/android/app/KeyguardManagerKosmos.kt new file mode 100644 index 000000000000..e5121d5de6dd --- /dev/null +++ b/packages/SystemUI/tests/utils/src/android/app/KeyguardManagerKosmos.kt @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.app + +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.util.mockito.mock + +val Kosmos.keyguardManager by Kosmos.Fixture { mock<KeyguardManager>() } diff --git a/packages/SystemUI/tests/utils/src/android/os/HandlerKosmos.kt b/packages/SystemUI/tests/utils/src/android/os/HandlerKosmos.kt new file mode 100644 index 000000000000..4e2683bd7a2f --- /dev/null +++ b/packages/SystemUI/tests/utils/src/android/os/HandlerKosmos.kt @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.os + +import com.android.systemui.concurrency.fakeExecutor +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.util.concurrency.mockExecutorHandler + +val Kosmos.fakeExecutorHandler by Kosmos.Fixture { mockExecutorHandler(fakeExecutor) } diff --git a/packages/SystemUI/tests/utils/src/android/service/dream/DreamManagerKosmos.kt b/packages/SystemUI/tests/utils/src/android/service/dream/DreamManagerKosmos.kt new file mode 100644 index 000000000000..fb51f0fec997 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/android/service/dream/DreamManagerKosmos.kt @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.service.dream + +import android.service.dreams.IDreamManager +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.util.mockito.mock + +var Kosmos.dreamManager by Kosmos.Fixture { mock<IDreamManager>() } diff --git a/packages/SystemUI/tests/utils/src/com/android/internal/widget/LockPatternUtilsKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/internal/widget/LockPatternUtilsKosmos.kt new file mode 100644 index 000000000000..d9ea5e92710c --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/internal/widget/LockPatternUtilsKosmos.kt @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.widget + +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.util.mockito.mock + +var Kosmos.lockPatternUtils by Kosmos.Fixture { mock<LockPatternUtils>() } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/ActivityIntentHelperKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/ActivityIntentHelperKosmos.kt new file mode 100644 index 000000000000..7185b7cd0ac6 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/ActivityIntentHelperKosmos.kt @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui + +import android.content.applicationContext +import com.android.systemui.kosmos.Kosmos + +val Kosmos.activityIntentHelper by Kosmos.Fixture { ActivityIntentHelper(applicationContext) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/animation/ActivityLaunchAnimatorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/animation/ActivityLaunchAnimatorKosmos.kt new file mode 100644 index 000000000000..128f58bf9751 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/animation/ActivityLaunchAnimatorKosmos.kt @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.animation + +import com.android.systemui.kosmos.Kosmos + +val Kosmos.activityLaunchAnimator by Kosmos.Fixture { ActivityLaunchAnimator() } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/assist/AssistManagerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/assist/AssistManagerKosmos.kt new file mode 100644 index 000000000000..b7d6f3a5f91f --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/assist/AssistManagerKosmos.kt @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.assist + +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.util.mockito.mock + +var Kosmos.assistManager by Kosmos.Fixture { mock<AssistManager>() } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalInteractorFactory.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalInteractorFactory.kt deleted file mode 100644 index 1753ca05347a..000000000000 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalInteractorFactory.kt +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (C) 2023 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package com.android.systemui.communal.domain.interactor - -import com.android.systemui.communal.data.repository.FakeCommunalMediaRepository -import com.android.systemui.communal.data.repository.FakeCommunalPrefsRepository -import com.android.systemui.communal.data.repository.FakeCommunalRepository -import com.android.systemui.communal.data.repository.FakeCommunalTutorialRepository -import com.android.systemui.communal.data.repository.FakeCommunalWidgetRepository -import com.android.systemui.communal.widgets.CommunalAppWidgetHost -import com.android.systemui.communal.widgets.EditWidgetsActivityStarter -import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository -import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor -import com.android.systemui.smartspace.data.repository.FakeSmartspaceRepository -import com.android.systemui.util.mockito.mock -import kotlinx.coroutines.test.TestScope - -object CommunalInteractorFactory { - - @JvmOverloads - @JvmStatic - fun create( - testScope: TestScope = TestScope(), - communalRepository: FakeCommunalRepository = - FakeCommunalRepository(testScope.backgroundScope), - widgetRepository: FakeCommunalWidgetRepository = - FakeCommunalWidgetRepository(testScope.backgroundScope), - mediaRepository: FakeCommunalMediaRepository = FakeCommunalMediaRepository(), - smartspaceRepository: FakeSmartspaceRepository = FakeSmartspaceRepository(), - tutorialRepository: FakeCommunalTutorialRepository = FakeCommunalTutorialRepository(), - communalPrefsRepository: FakeCommunalPrefsRepository = FakeCommunalPrefsRepository(), - appWidgetHost: CommunalAppWidgetHost = mock(), - editWidgetsActivityStarter: EditWidgetsActivityStarter = mock(), - ): WithDependencies { - val withDeps = - CommunalTutorialInteractorFactory.create( - testScope = testScope, - communalTutorialRepository = tutorialRepository, - communalRepository = communalRepository, - ) - return WithDependencies( - testScope, - communalRepository, - widgetRepository, - communalPrefsRepository, - mediaRepository, - smartspaceRepository, - tutorialRepository, - withDeps.keyguardRepository, - withDeps.keyguardInteractor, - withDeps.communalTutorialInteractor, - appWidgetHost, - editWidgetsActivityStarter, - CommunalInteractor( - testScope.backgroundScope, - communalRepository, - widgetRepository, - communalPrefsRepository, - mediaRepository, - smartspaceRepository, - withDeps.keyguardInteractor, - appWidgetHost, - editWidgetsActivityStarter, - ), - ) - } - - data class WithDependencies( - val testScope: TestScope, - val communalRepository: FakeCommunalRepository, - val widgetRepository: FakeCommunalWidgetRepository, - val communalPrefsRepository: FakeCommunalPrefsRepository, - val mediaRepository: FakeCommunalMediaRepository, - val smartspaceRepository: FakeSmartspaceRepository, - val tutorialRepository: FakeCommunalTutorialRepository, - val keyguardRepository: FakeKeyguardRepository, - val keyguardInteractor: KeyguardInteractor, - val tutorialInteractor: CommunalTutorialInteractor, - val appWidgetHost: CommunalAppWidgetHost, - val editWidgetsActivityStarter: EditWidgetsActivityStarter, - val communalInteractor: CommunalInteractor, - ) -} diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalInteractorKosmos.kt index 65579a6d9ddf..1abf71fde14c 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalInteractorKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalInteractorKosmos.kt @@ -20,11 +20,13 @@ import com.android.systemui.communal.data.repository.communalMediaRepository import com.android.systemui.communal.data.repository.communalPrefsRepository import com.android.systemui.communal.data.repository.communalRepository import com.android.systemui.communal.data.repository.communalWidgetRepository +import com.android.systemui.communal.widgets.EditWidgetsActivityStarter import com.android.systemui.keyguard.domain.interactor.keyguardInteractor import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.Kosmos.Fixture import com.android.systemui.kosmos.applicationCoroutineScope import com.android.systemui.smartspace.data.repository.smartspaceRepository +import com.android.systemui.user.data.repository.userRepository import com.android.systemui.util.mockito.mock val Kosmos.communalInteractor by Fixture { @@ -35,8 +37,11 @@ val Kosmos.communalInteractor by Fixture { mediaRepository = communalMediaRepository, communalPrefsRepository = communalPrefsRepository, smartspaceRepository = smartspaceRepository, + userRepository = userRepository, appWidgetHost = mock(), keyguardInteractor = keyguardInteractor, - editWidgetsActivityStarter = mock(), + editWidgetsActivityStarter = editWidgetsActivityStarter, ) } + +val Kosmos.editWidgetsActivityStarter by Fixture<EditWidgetsActivityStarter> { mock() } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalTutorialInteractorFactory.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalTutorialInteractorFactory.kt deleted file mode 100644 index 3ff2a3ed5145..000000000000 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalTutorialInteractorFactory.kt +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2023 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.systemui.communal.domain.interactor - -import com.android.systemui.communal.data.repository.FakeCommunalRepository -import com.android.systemui.communal.data.repository.FakeCommunalTutorialRepository -import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository -import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor -import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory -import kotlinx.coroutines.test.TestScope - -object CommunalTutorialInteractorFactory { - - @JvmOverloads - @JvmStatic - fun create( - testScope: TestScope, - communalTutorialRepository: FakeCommunalTutorialRepository = - FakeCommunalTutorialRepository(), - communalRepository: FakeCommunalRepository = - FakeCommunalRepository(applicationScope = testScope.backgroundScope), - keyguardRepository: FakeKeyguardRepository = FakeKeyguardRepository(), - keyguardInteractor: KeyguardInteractor = - KeyguardInteractorFactory.create( - repository = keyguardRepository, - ) - .keyguardInteractor - ): WithDependencies { - return WithDependencies( - testScope = testScope, - communalRepository = communalRepository, - communalTutorialRepository = communalTutorialRepository, - keyguardRepository = keyguardRepository, - keyguardInteractor = keyguardInteractor, - communalTutorialInteractor = - CommunalTutorialInteractor( - testScope.backgroundScope, - communalTutorialRepository, - keyguardInteractor, - communalRepository, - ) - ) - } - - data class WithDependencies( - val testScope: TestScope, - val communalRepository: FakeCommunalRepository, - val communalTutorialRepository: FakeCommunalTutorialRepository, - val keyguardRepository: FakeKeyguardRepository, - val keyguardInteractor: KeyguardInteractor, - val communalTutorialInteractor: CommunalTutorialInteractor, - ) -} diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalTutorialInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalTutorialInteractorKosmos.kt new file mode 100644 index 000000000000..adaea7cbf64d --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalTutorialInteractorKosmos.kt @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.communal.domain.interactor + +import com.android.systemui.communal.data.repository.communalRepository +import com.android.systemui.communal.data.repository.communalTutorialRepository +import com.android.systemui.keyguard.domain.interactor.keyguardInteractor +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.kosmos.applicationCoroutineScope + +val Kosmos.communalTutorialInteractor by + Kosmos.Fixture { + CommunalTutorialInteractor( + scope = applicationCoroutineScope, + communalTutorialRepository = communalTutorialRepository, + keyguardInteractor = keyguardInteractor, + communalRepository = communalRepository, + communalInteractor = communalInteractor, + ) + } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/data/repository/FakeStickyKeysRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/data/repository/FakeStickyKeysRepository.kt new file mode 100644 index 000000000000..68e14573a9b2 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/data/repository/FakeStickyKeysRepository.kt @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.keyboard.data.repository + +import com.android.systemui.keyboard.stickykeys.data.repository.StickyKeysRepository +import com.android.systemui.keyboard.stickykeys.shared.model.Locked +import com.android.systemui.keyboard.stickykeys.shared.model.ModifierKey +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow + +class FakeStickyKeysRepository : StickyKeysRepository { + override val settingEnabled: Flow<Boolean> = MutableStateFlow(true) + private val _stickyKeys: MutableStateFlow<LinkedHashMap<ModifierKey, Locked>> = + MutableStateFlow(LinkedHashMap()) + + override val stickyKeys: Flow<LinkedHashMap<ModifierKey, Locked>> = _stickyKeys + + fun setStickyKeys(keys: LinkedHashMap<ModifierKey, Locked>) { + _stickyKeys.value = keys + } +} diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/data/repository/KeyboardRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/data/repository/KeyboardRepositoryKosmos.kt new file mode 100644 index 000000000000..46f7355dfe75 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/data/repository/KeyboardRepositoryKosmos.kt @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.keyboard.data.repository + +import com.android.systemui.kosmos.Kosmos + +val Kosmos.keyboardRepository by Kosmos.Fixture { FakeKeyboardRepository() }
\ No newline at end of file diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt index 59f56dd18f0e..5766f7a9028c 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt @@ -130,6 +130,8 @@ class FakeKeyguardRepository @Inject constructor() : KeyguardRepository { private val _isEncryptedOrLockdown = MutableStateFlow(true) override val isEncryptedOrLockdown: Flow<Boolean> = _isEncryptedOrLockdown + override val topClippingBounds = MutableStateFlow<Int?>(null) + override fun setQuickSettingsVisible(isVisible: Boolean) { _isQuickSettingsVisible.value = isVisible } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/CommunalInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/CommunalInteractorKosmos.kt deleted file mode 100644 index d8f0cec54596..000000000000 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/CommunalInteractorKosmos.kt +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2024 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.systemui.keyguard.domain.interactor - -import com.android.systemui.communal.data.repository.communalMediaRepository -import com.android.systemui.communal.data.repository.communalPrefsRepository -import com.android.systemui.communal.data.repository.communalRepository -import com.android.systemui.communal.data.repository.communalWidgetRepository -import com.android.systemui.communal.domain.interactor.CommunalInteractor -import com.android.systemui.communal.widgets.CommunalAppWidgetHost -import com.android.systemui.communal.widgets.EditWidgetsActivityStarter -import com.android.systemui.kosmos.Kosmos -import com.android.systemui.kosmos.testScope -import com.android.systemui.smartspace.data.repository.smartspaceRepository -import org.mockito.Mockito.mock - -val Kosmos.communalInteractor by - Kosmos.Fixture { - CommunalInteractor( - applicationScope = testScope.backgroundScope, - communalRepository = communalRepository, - widgetRepository = communalWidgetRepository, - mediaRepository = communalMediaRepository, - communalPrefsRepository = communalPrefsRepository, - smartspaceRepository = smartspaceRepository, - keyguardInteractor = keyguardInteractor, - appWidgetHost = mock(CommunalAppWidgetHost::class.java), - editWidgetsActivityStarter = editWidgetsActivityStarter, - ) - } - -val Kosmos.editWidgetsActivityStarter by - Kosmos.Fixture<EditWidgetsActivityStarter> { mock(EditWidgetsActivityStarter::class.java) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractorKosmos.kt index 97536e20cb0a..719686e3d862 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractorKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractorKosmos.kt @@ -17,6 +17,7 @@ package com.android.systemui.keyguard.domain.interactor import com.android.keyguard.keyguardSecurityModel +import com.android.systemui.communal.domain.interactor.communalInteractor import com.android.systemui.flags.featureFlagsClassic import com.android.systemui.keyguard.data.repository.keyguardTransitionRepository import com.android.systemui.kosmos.Kosmos @@ -34,6 +35,7 @@ val Kosmos.fromPrimaryBouncerTransitionInteractor by bgDispatcher = testDispatcher, mainDispatcher = testDispatcher, keyguardInteractor = keyguardInteractor, + communalInteractor = communalInteractor, flags = featureFlagsClassic, keyguardSecurityModel = keyguardSecurityModel, selectedUserInteractor = selectedUserInteractor, diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/GlanceableHubTransitionsKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/GlanceableHubTransitionsKosmos.kt index 294b5ba474c3..55885bf58acc 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/GlanceableHubTransitionsKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/GlanceableHubTransitionsKosmos.kt @@ -16,14 +16,17 @@ package com.android.systemui.keyguard.domain.interactor +import com.android.systemui.communal.domain.interactor.communalInteractor import com.android.systemui.keyguard.data.repository.keyguardTransitionRepository import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.applicationCoroutineScope +import com.android.systemui.kosmos.testDispatcher val Kosmos.glanceableHubTransitions by Kosmos.Fixture { GlanceableHubTransitions( scope = applicationCoroutineScope, + bgDispatcher = testDispatcher, transitionRepository = keyguardTransitionRepository, transitionInteractor = keyguardTransitionInteractor, communalInteractor = communalInteractor, diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelKosmos.kt index 5564767e0715..d376f126e2c9 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelKosmos.kt @@ -18,6 +18,7 @@ package com.android.systemui.keyguard.ui.viewmodel +import com.android.systemui.communal.domain.interactor.communalInteractor import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor import com.android.systemui.keyguard.domain.interactor.keyguardInteractor import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor @@ -33,6 +34,7 @@ val Kosmos.keyguardRootViewModel by Fixture { deviceEntryInteractor = deviceEntryInteractor, dozeParameters = dozeParameters, keyguardInteractor = keyguardInteractor, + communalInteractor = communalInteractor, keyguardTransitionInteractor = keyguardTransitionInteractor, notificationsKeyguardInteractor = notificationsKeyguardInteractor, aodToLockscreenTransitionViewModel = aodToLockscreenTransitionViewModel, diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt index cc0449d7e7bb..321f94468a2e 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt @@ -26,6 +26,7 @@ import com.android.systemui.classifier.falsingCollector import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository import com.android.systemui.common.ui.domain.interactor.configurationInteractor import com.android.systemui.communal.data.repository.fakeCommunalRepository +import com.android.systemui.communal.domain.interactor.communalInteractor import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor import com.android.systemui.deviceentry.domain.interactor.deviceUnlockedInteractor import com.android.systemui.flags.fakeFeatureFlagsClassic @@ -72,6 +73,7 @@ class KosmosJavaAdapter( val powerInteractor by lazy { kosmos.powerInteractor } val deviceEntryInteractor by lazy { kosmos.deviceEntryInteractor } val deviceUnlockedInteractor by lazy { kosmos.deviceUnlockedInteractor } + val communalInteractor by lazy { kosmos.communalInteractor } init { kosmos.applicationContext = testCase.context diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ShadeControllerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ShadeControllerKosmos.kt new file mode 100644 index 000000000000..7cc5d6b6243a --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ShadeControllerKosmos.kt @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.shade + +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.util.mockito.mock + +var Kosmos.shadeController by Kosmos.Fixture { mock<ShadeController>() } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ShadeViewControllerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ShadeViewControllerKosmos.kt new file mode 100644 index 000000000000..1ceab68604f3 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ShadeViewControllerKosmos.kt @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.shade + +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.util.mockito.mock + +var Kosmos.shadeViewController by Kosmos.Fixture { mock<ShadeViewController>() } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/data/repository/ShadeAnimationRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/data/repository/ShadeAnimationRepositoryKosmos.kt new file mode 100644 index 000000000000..4dcd2208b152 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/data/repository/ShadeAnimationRepositoryKosmos.kt @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.shade.data.repository + +import com.android.systemui.kosmos.Kosmos + +val Kosmos.shadeAnimationRepository by Kosmos.Fixture { ShadeAnimationRepository() } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractorKosmos.kt new file mode 100644 index 000000000000..57b272f10c67 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeAnimationInteractorKosmos.kt @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.shade.domain.interactor + +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.shade.data.repository.shadeAnimationRepository + +var Kosmos.shadeAnimationInteractor: ShadeAnimationInteractor by + Kosmos.Fixture { ShadeAnimationInteractorEmptyImpl(shadeAnimationRepository) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shared/notifications/data/repository/NotificationSettingsRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shared/notifications/data/repository/NotificationSettingsRepositoryKosmos.kt new file mode 100644 index 000000000000..a75d2bc4aaf6 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shared/notifications/data/repository/NotificationSettingsRepositoryKosmos.kt @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.shared.notifications.data.repository + +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.kosmos.testDispatcher +import com.android.systemui.kosmos.testScope +import com.android.systemui.shared.settings.data.repository.secureSettingsRepository + +val Kosmos.notificationSettingsRepository by + Kosmos.Fixture { + NotificationSettingsRepository( + scope = testScope.backgroundScope, + backgroundDispatcher = testDispatcher, + secureSettingsRepository = secureSettingsRepository, + ) + } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shared/notifications/domain/interactor/NotificationSettingsInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shared/notifications/domain/interactor/NotificationSettingsInteractorKosmos.kt new file mode 100644 index 000000000000..17b4603e17b9 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shared/notifications/domain/interactor/NotificationSettingsInteractorKosmos.kt @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.shared.notifications.domain.interactor + +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.shared.notifications.data.repository.notificationSettingsRepository + +val Kosmos.notificationSettingsInteractor by + Kosmos.Fixture { NotificationSettingsInteractor(notificationSettingsRepository) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shared/settings/data/repository/SecureSettingsRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shared/settings/data/repository/SecureSettingsRepositoryKosmos.kt new file mode 100644 index 000000000000..552b09e933de --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shared/settings/data/repository/SecureSettingsRepositoryKosmos.kt @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.shared.settings.data.repository + +import com.android.systemui.kosmos.Kosmos + +var Kosmos.secureSettingsRepository: SecureSettingsRepository by + Kosmos.Fixture { fakeSecureSettingsRepository } +val Kosmos.fakeSecureSettingsRepository by Kosmos.Fixture { FakeSecureSettingsRepository() } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/NotificationClickNotifierKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/NotificationClickNotifierKosmos.kt new file mode 100644 index 000000000000..7b912aef3011 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/NotificationClickNotifierKosmos.kt @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar + +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.util.mockito.mock + +var Kosmos.notificationClickNotifier by Kosmos.Fixture { mock<NotificationClickNotifier>() } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/NotificationPresenterKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/NotificationPresenterKosmos.kt new file mode 100644 index 000000000000..8d30049bfb09 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/NotificationPresenterKosmos.kt @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar + +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.util.mockito.mock + +var Kosmos.notificationPresenter by Kosmos.Fixture { mock<NotificationPresenter>() } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/NotificationRemoteInputManagerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/NotificationRemoteInputManagerKosmos.kt new file mode 100644 index 000000000000..554bdbe0c382 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/NotificationRemoteInputManagerKosmos.kt @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar + +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.util.mockito.mock + +var Kosmos.notificationRemoteInputManager by + Kosmos.Fixture { mock<NotificationRemoteInputManager>() } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/NotificationShadeWindowControllerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/NotificationShadeWindowControllerKosmos.kt new file mode 100644 index 000000000000..e8ca3b8234e8 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/NotificationShadeWindowControllerKosmos.kt @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar + +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.util.mockito.mock + +var Kosmos.notificationShadeWindowController by + Kosmos.Fixture { mock<NotificationShadeWindowController>() } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/NotificationActivityStarterKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/NotificationActivityStarterKosmos.kt new file mode 100644 index 000000000000..c337ac201b3d --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/NotificationActivityStarterKosmos.kt @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.notification + +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.statusbar.phone.statusBarNotificationActivityStarter + +var Kosmos.notificationActivityStarter: NotificationActivityStarter by + Kosmos.Fixture { statusBarNotificationActivityStarter } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorControllerProviderKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorControllerProviderKosmos.kt new file mode 100644 index 000000000000..c3db34bdddb7 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorControllerProviderKosmos.kt @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.notification + +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.util.mockito.mock + +var Kosmos.notificationLaunchAnimatorControllerProvider by + Kosmos.Fixture { mock<NotificationLaunchAnimatorControllerProvider>() } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataStoreKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataStoreKosmos.kt new file mode 100644 index 000000000000..1f45fbbcf927 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataStoreKosmos.kt @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.notification.collection + +import com.android.systemui.concurrency.fakeExecutor +import com.android.systemui.kosmos.Kosmos + +var Kosmos.notifLiveDataStore: NotifLiveDataStore by + Kosmos.Fixture { NotifLiveDataStoreImpl(fakeExecutor) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinatorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinatorKosmos.kt new file mode 100644 index 000000000000..358d2519556b --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinatorKosmos.kt @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.notification.collection.coordinator + +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.util.mockito.mock + +var Kosmos.visualStabilityCoordinator by Kosmos.Fixture { mock<VisualStabilityCoordinator>() } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/collection/provider/LaunchFullScreenIntentProviderKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/collection/provider/LaunchFullScreenIntentProviderKosmos.kt new file mode 100644 index 000000000000..a5c956155351 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/collection/provider/LaunchFullScreenIntentProviderKosmos.kt @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.notification.collection.provider + +import com.android.systemui.kosmos.Kosmos + +val Kosmos.launchFullScreenIntentProvider by Kosmos.Fixture { LaunchFullScreenIntentProvider() } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/collection/render/NotificationVisibilityProviderKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/collection/render/NotificationVisibilityProviderKosmos.kt new file mode 100644 index 000000000000..edce5d58b351 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/collection/render/NotificationVisibilityProviderKosmos.kt @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.notification.collection.render + +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.statusbar.notification.collection.notifLiveDataStore +import com.android.systemui.statusbar.notification.collection.notifPipeline +import com.android.systemui.statusbar.notification.collection.provider.NotificationVisibilityProviderImpl +import com.android.systemui.statusbar.notification.domain.interactor.activeNotificationsInteractor + +var Kosmos.notificationVisibilityProvider: NotificationVisibilityProvider by + Kosmos.Fixture { + NotificationVisibilityProviderImpl( + activeNotificationsInteractor, + notifLiveDataStore, + notifPipeline, + ) + } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/OnUserInteractionCallbackKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/OnUserInteractionCallbackKosmos.kt new file mode 100644 index 000000000000..1e3897ba46c6 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/OnUserInteractionCallbackKosmos.kt @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.notification.row + +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.plugins.statusbar.statusBarStateController +import com.android.systemui.statusbar.notification.collection.coordinator.visualStabilityCoordinator +import com.android.systemui.statusbar.notification.collection.inflation.OnUserInteractionCallbackImpl +import com.android.systemui.statusbar.notification.collection.notifCollection +import com.android.systemui.statusbar.notification.collection.render.notificationVisibilityProvider +import com.android.systemui.statusbar.policy.headsUpManager + +var Kosmos.onUserInteractionCallback: OnUserInteractionCallback by + Kosmos.Fixture { + OnUserInteractionCallbackImpl( + notificationVisibilityProvider, + notifCollection, + headsUpManager, + statusBarStateController, + visualStabilityCoordinator, + ) + } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelKosmos.kt index 5ef9a8e8edd8..db4050905200 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelKosmos.kt @@ -16,8 +16,11 @@ package com.android.systemui.statusbar.notification.stack.ui.viewmodel +import com.android.systemui.communal.domain.interactor.communalInteractor import com.android.systemui.keyguard.domain.interactor.keyguardInteractor import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor +import com.android.systemui.keyguard.ui.viewmodel.glanceableHubToLockscreenTransitionViewModel +import com.android.systemui.keyguard.ui.viewmodel.lockscreenToGlanceableHubTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.lockscreenToOccludedTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.occludedToLockscreenTransitionViewModel import com.android.systemui.kosmos.Kosmos @@ -33,7 +36,10 @@ val Kosmos.sharedNotificationContainerViewModel by Fixture { keyguardInteractor = keyguardInteractor, keyguardTransitionInteractor = keyguardTransitionInteractor, shadeInteractor = shadeInteractor, + communalInteractor = communalInteractor, occludedToLockscreenTransitionViewModel = occludedToLockscreenTransitionViewModel, lockscreenToOccludedTransitionViewModel = lockscreenToOccludedTransitionViewModel, + glanceableHubToLockscreenTransitionViewModel = glanceableHubToLockscreenTransitionViewModel, + lockscreenToGlanceableHubTransitionViewModel = lockscreenToGlanceableHubTransitionViewModel ) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterKosmos.kt new file mode 100644 index 000000000000..6ddc9df930f3 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterKosmos.kt @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.phone + +import android.app.keyguardManager +import android.content.applicationContext +import android.os.fakeExecutorHandler +import android.service.dream.dreamManager +import com.android.internal.logging.metricsLogger +import com.android.internal.widget.lockPatternUtils +import com.android.systemui.activityIntentHelper +import com.android.systemui.animation.activityLaunchAnimator +import com.android.systemui.assist.assistManager +import com.android.systemui.concurrency.fakeExecutor +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.plugins.activityStarter +import com.android.systemui.power.domain.interactor.powerInteractor +import com.android.systemui.settings.userTracker +import com.android.systemui.shade.domain.interactor.shadeAnimationInteractor +import com.android.systemui.shade.shadeController +import com.android.systemui.shade.shadeViewController +import com.android.systemui.statusbar.notification.collection.provider.launchFullScreenIntentProvider +import com.android.systemui.statusbar.notification.collection.render.notificationVisibilityProvider +import com.android.systemui.statusbar.notification.notificationLaunchAnimatorControllerProvider +import com.android.systemui.statusbar.notification.row.onUserInteractionCallback +import com.android.systemui.statusbar.notificationClickNotifier +import com.android.systemui.statusbar.notificationLockscreenUserManager +import com.android.systemui.statusbar.notificationPresenter +import com.android.systemui.statusbar.notificationRemoteInputManager +import com.android.systemui.statusbar.notificationShadeWindowController +import com.android.systemui.statusbar.policy.headsUpManager +import com.android.systemui.statusbar.policy.keyguardStateController +import com.android.systemui.wmshell.bubblesManager +import java.util.Optional +import kotlinx.coroutines.ExperimentalCoroutinesApi + +@OptIn(ExperimentalCoroutinesApi::class) +val Kosmos.statusBarNotificationActivityStarter by + Kosmos.Fixture { + StatusBarNotificationActivityStarter( + applicationContext, + applicationContext.displayId, + fakeExecutorHandler, + fakeExecutor, + notificationVisibilityProvider, + headsUpManager, + activityStarter, + notificationClickNotifier, + statusBarKeyguardViewManager, + keyguardManager, + dreamManager, + Optional.of(bubblesManager), + { assistManager }, + notificationRemoteInputManager, + notificationLockscreenUserManager, + shadeController, + keyguardStateController, + lockPatternUtils, + statusBarRemoteInputCallback, + activityIntentHelper, + metricsLogger, + statusBarNotificationActivityStarterLogger, + onUserInteractionCallback, + notificationPresenter, + shadeViewController, + notificationShadeWindowController, + activityLaunchAnimator, + shadeAnimationInteractor, + notificationLaunchAnimatorControllerProvider, + launchFullScreenIntentProvider, + powerInteractor, + userTracker, + ) + } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterLoggerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterLoggerKosmos.kt new file mode 100644 index 000000000000..31cfc979a11a --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterLoggerKosmos.kt @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.phone + +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.log.logcatLogBuffer + +val Kosmos.statusBarNotificationActivityStarterLogger by + Kosmos.Fixture { StatusBarNotificationActivityStarterLogger(logcatLogBuffer()) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackKosmos.kt new file mode 100644 index 000000000000..475d7fa6ef4b --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackKosmos.kt @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.phone + +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.util.mockito.mock + +var Kosmos.statusBarRemoteInputCallback by Kosmos.Fixture { mock<StatusBarRemoteInputCallback>() } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionRepository.kt index a9c8ec7dcb7d..32d572ef9dee 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionRepository.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeMobileConnectionRepository.kt @@ -35,6 +35,7 @@ class FakeMobileConnectionRepository( override val isRoaming = MutableStateFlow(false) override val operatorAlphaShort: MutableStateFlow<String?> = MutableStateFlow(null) override val isInService = MutableStateFlow(false) + override val isNonTerrestrial = MutableStateFlow(false) override val isGsm = MutableStateFlow(false) override val cdmaLevel = MutableStateFlow(0) override val primaryLevel = MutableStateFlow(0) diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/KeyguardStateControllerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/KeyguardStateControllerKosmos.kt new file mode 100644 index 000000000000..0e909c498a2b --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/KeyguardStateControllerKosmos.kt @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.policy + +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.util.mockito.mock + +var Kosmos.keyguardStateController by Kosmos.Fixture { mock<KeyguardStateController>() } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/ui/SystemBarUtilsStateKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/ui/SystemBarUtilsStateKosmos.kt index e208add32efa..5476d5509c0c 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/ui/SystemBarUtilsStateKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/ui/SystemBarUtilsStateKosmos.kt @@ -17,7 +17,15 @@ package com.android.systemui.statusbar.ui import com.android.systemui.kosmos.Kosmos +import com.android.systemui.kosmos.Kosmos.Fixture +import com.android.systemui.kosmos.testDispatcher import com.android.systemui.statusbar.policy.configurationController -val Kosmos.systemBarUtilsState by - Kosmos.Fixture { SystemBarUtilsState(configurationController, systemBarUtilsProxy) } +val Kosmos.systemBarUtilsState by Fixture { + SystemBarUtilsState( + testDispatcher, + testDispatcher, + configurationController, + systemBarUtilsProxy, + ) +} diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/wmshell/BubblesManagerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/wmshell/BubblesManagerKosmos.kt new file mode 100644 index 000000000000..1d05d62a02e4 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/wmshell/BubblesManagerKosmos.kt @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.wmshell + +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.util.mockito.mock + +var Kosmos.bubblesManager by Kosmos.Fixture { mock<BubblesManager>() } diff --git a/packages/VpnDialogs/res/values-zh-rTW/strings.xml b/packages/VpnDialogs/res/values-zh-rTW/strings.xml index 3f1336be9184..7d5e86786d7d 100644 --- a/packages/VpnDialogs/res/values-zh-rTW/strings.xml +++ b/packages/VpnDialogs/res/values-zh-rTW/strings.xml @@ -25,7 +25,7 @@ <string name="data_transmitted" msgid="7988167672982199061">"已傳送:"</string> <string name="data_received" msgid="4062776929376067820">"已接收:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> 位元組 / <xliff:g id="NUMBER_1">%2$s</xliff:g> 個封包"</string> - <string name="always_on_disconnected_title" msgid="1906740176262776166">"無法連上永久連線的 VPN"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"無法連上永久連線 VPN"</string> <string name="always_on_disconnected_message" msgid="555634519845992917">"「<xliff:g id="VPN_APP_0">%1$s</xliff:g>」設定為隨時保持連線,但目前無法連線。在重新連上「<xliff:g id="VPN_APP_1">%1$s</xliff:g>」之前,你的手機將會使用公用網路。"</string> <string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"「<xliff:g id="VPN_APP">%1$s</xliff:g>」設定為隨時保持連線,但目前無法連線。在重新連上 VPN 之前,你將無法連接網路。"</string> <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> diff --git a/packages/overlays/NavigationBarModeGesturalOverlay/res/values-sw600dp/config.xml b/packages/overlays/NavigationBarModeGesturalOverlay/res/values-sw600dp/config.xml new file mode 100644 index 000000000000..be1f081d5b8f --- /dev/null +++ b/packages/overlays/NavigationBarModeGesturalOverlay/res/values-sw600dp/config.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * Copyright (c) 2023, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--> +<resources> + <!-- If true, attach the navigation bar to the app during app transition --> + <bool name="config_attachNavBarToAppDuringTransition">false</bool> +</resources> diff --git a/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/res/values-sw600dp/config.xml b/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/res/values-sw600dp/config.xml new file mode 100644 index 000000000000..be1f081d5b8f --- /dev/null +++ b/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/res/values-sw600dp/config.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * Copyright (c) 2023, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--> +<resources> + <!-- If true, attach the navigation bar to the app during app transition --> + <bool name="config_attachNavBarToAppDuringTransition">false</bool> +</resources> diff --git a/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/res/values-sw600dp/config.xml b/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/res/values-sw600dp/config.xml new file mode 100644 index 000000000000..be1f081d5b8f --- /dev/null +++ b/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/res/values-sw600dp/config.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * Copyright (c) 2023, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--> +<resources> + <!-- If true, attach the navigation bar to the app during app transition --> + <bool name="config_attachNavBarToAppDuringTransition">false</bool> +</resources> diff --git a/packages/overlays/NavigationBarModeGesturalOverlayWideBack/res/values-sw600dp/config.xml b/packages/overlays/NavigationBarModeGesturalOverlayWideBack/res/values-sw600dp/config.xml new file mode 100644 index 000000000000..be1f081d5b8f --- /dev/null +++ b/packages/overlays/NavigationBarModeGesturalOverlayWideBack/res/values-sw600dp/config.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/** + * Copyright (c) 2023, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--> +<resources> + <!-- If true, attach the navigation bar to the app during app transition --> + <bool name="config_attachNavBarToAppDuringTransition">false</bool> +</resources> diff --git a/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java b/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java index 7fcef9c90812..3aa9cc84e9f6 100644 --- a/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java +++ b/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java @@ -59,6 +59,7 @@ import android.hardware.camera2.extension.Request; import android.hardware.camera2.extension.SizeList; import android.hardware.camera2.impl.CameraMetadataNative; import android.hardware.camera2.impl.PhysicalCaptureResultInfo; +import android.hardware.camera2.utils.SurfaceUtils; import android.media.Image; import android.media.ImageReader; import android.os.Binder; @@ -1691,11 +1692,17 @@ public class CameraExtensionsProxyService extends Service { private final Surface mSurface; private final Size mSize; private final int mImageFormat; + private final int mDataspace; public OutputSurfaceImplStub(OutputSurface outputSurface) { mSurface = outputSurface.surface; mSize = new Size(outputSurface.size.width, outputSurface.size.height); mImageFormat = outputSurface.imageFormat; + if (mSurface != null) { + mDataspace = SurfaceUtils.getSurfaceDataspace(mSurface); + } else { + mDataspace = -1; + } } @Override @@ -1712,6 +1719,11 @@ public class CameraExtensionsProxyService extends Service { public int getImageFormat() { return mImageFormat; } + + @Override + public int getDataspace() { + return mDataspace; + } } private class PreviewExtenderImplStub extends IPreviewExtenderImpl.Stub implements diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java index 3d8d7b738233..d656892062d1 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java @@ -4413,25 +4413,50 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub @Override public boolean isAccessibilityServiceWarningRequired(AccessibilityServiceInfo info) { mSecurityPolicy.enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ACCESSIBILITY); + final ComponentName componentName = info.getComponentName(); // Warning is not required if the service is already enabled. synchronized (mLock) { final AccessibilityUserState userState = getCurrentUserStateLocked(); - if (userState.getEnabledServicesLocked().contains(info.getComponentName())) { + if (userState.getEnabledServicesLocked().contains(componentName)) { return false; } } // Warning is not required if the service is already assigned to a shortcut. for (int shortcutType : AccessibilityManager.SHORTCUT_TYPES) { if (getAccessibilityShortcutTargets(shortcutType).contains( - info.getComponentName().flattenToString())) { + componentName.flattenToString())) { return false; } } + // Warning is not required if the service is preinstalled and in the + // trustedAccessibilityServices allowlist. + if (android.view.accessibility.Flags.skipAccessibilityWarningDialogForTrustedServices() + && isAccessibilityServicePreinstalledAndTrusted(info)) { + return false; + } + // Warning is required by default. return true; } + private boolean isAccessibilityServicePreinstalledAndTrusted(AccessibilityServiceInfo info) { + final ComponentName componentName = info.getComponentName(); + final boolean isPreinstalled = + info.getResolveInfo().serviceInfo.applicationInfo.isSystemApp(); + if (isPreinstalled) { + final String[] trustedAccessibilityServices = + mContext.getResources().getStringArray( + R.array.config_trustedAccessibilityServices); + if (Arrays.stream(trustedAccessibilityServices) + .map(ComponentName::unflattenFromString) + .anyMatch(componentName::equals)) { + return true; + } + } + return false; + } + @Override public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) { if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, pw)) return; diff --git a/services/autofill/bugfixes.aconfig b/services/autofill/bugfixes.aconfig index b5130a1c4cfc..ced10fbeff0c 100644 --- a/services/autofill/bugfixes.aconfig +++ b/services/autofill/bugfixes.aconfig @@ -34,3 +34,10 @@ flag { description: "Mitigation for autofill providers miscalculating view visibility" bug: "291795358" } + +flag { + name: "remote_fill_service_use_weak_reference" + namespace: "autofill" + description: "Use weak reference to address binder leak problem" + bug: "307972253" +} diff --git a/services/autofill/java/com/android/server/autofill/RemoteFillService.java b/services/autofill/java/com/android/server/autofill/RemoteFillService.java index 6d0915bf7d92..5c93991bef8c 100644 --- a/services/autofill/java/com/android/server/autofill/RemoteFillService.java +++ b/services/autofill/java/com/android/server/autofill/RemoteFillService.java @@ -17,6 +17,7 @@ package com.android.server.autofill; import static android.service.autofill.FillRequest.INVALID_REQUEST_ID; +import static android.service.autofill.Flags.remoteFillServiceUseWeakReference; import static com.android.server.autofill.Helper.sVerbose; @@ -44,6 +45,7 @@ import com.android.internal.infra.AbstractRemoteService; import com.android.internal.infra.ServiceConnector; import com.android.internal.os.IResultReceiver; +import java.lang.ref.WeakReference; import java.util.concurrent.CancellationException; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; @@ -65,6 +67,8 @@ final class RemoteFillService extends ServiceConnector.Impl<IAutoFillService> { private final Object mLock = new Object(); private CompletableFuture<FillResponse> mPendingFillRequest; private int mPendingFillRequestId = INVALID_REQUEST_ID; + private AtomicReference<IFillCallback> mFillCallback; + private AtomicReference<ISaveCallback> mSaveCallback; private final ComponentName mComponentName; private final boolean mIsCredentialAutofillService; @@ -150,6 +154,89 @@ final class RemoteFillService extends ServiceConnector.Impl<IAutoFillService> { } } + static class IFillCallbackDelegate extends IFillCallback.Stub { + private WeakReference<IFillCallback> mCallbackWeakRef; + + IFillCallbackDelegate(IFillCallback callback) { + mCallbackWeakRef = new WeakReference(callback); + } + + @Override + public void onCancellable(ICancellationSignal cancellation) throws RemoteException { + IFillCallback callback = mCallbackWeakRef.get(); + if (callback != null) { + callback.onCancellable(cancellation); + } + } + + @Override + public void onSuccess(FillResponse response) throws RemoteException { + IFillCallback callback = mCallbackWeakRef.get(); + if (callback != null) { + callback.onSuccess(response); + } + } + + @Override + public void onFailure(int requestId, CharSequence message) throws RemoteException { + IFillCallback callback = mCallbackWeakRef.get(); + if (callback != null) { + callback.onFailure(requestId, message); + } + } + } + + static class ISaveCallbackDelegate extends ISaveCallback.Stub { + + private WeakReference<ISaveCallback> mCallbackWeakRef; + + ISaveCallbackDelegate(ISaveCallback callback) { + mCallbackWeakRef = new WeakReference(callback); + } + + @Override + public void onSuccess(IntentSender intentSender) throws RemoteException { + ISaveCallback callback = mCallbackWeakRef.get(); + if (callback != null) { + callback.onSuccess(intentSender); + } + } + + @Override + public void onFailure(CharSequence message) throws RemoteException { + ISaveCallback callback = mCallbackWeakRef.get(); + if (callback != null) { + callback.onFailure(message); + } + } + } + + /** + * Wraps an {@link IFillCallback} object using weak reference. + * + * This prevents lingering allocation issue by breaking the chain of strong references from + * Binder to {@link callback}. Since {@link callback} is not held by Binder anymore, it needs + * to be held by {@link mFillCallback} so it's not deallocated prematurely. + */ + private IFillCallback maybeWrapWithWeakReference(IFillCallback callback) { + if (remoteFillServiceUseWeakReference()) { + mFillCallback = new AtomicReference<>(callback); + return new IFillCallbackDelegate(callback); + } + return callback; + } + + /** + * Wraps an {@link ISaveCallback} object using weak reference. + */ + private ISaveCallback maybeWrapWithWeakReference(ISaveCallback callback) { + if (remoteFillServiceUseWeakReference()) { + mSaveCallback = new AtomicReference<>(callback); + return new ISaveCallbackDelegate(callback); + } + return callback; + } + public void onFillCredentialRequest(@NonNull FillRequest request, IAutoFillManagerClient autofillCallback) { if (sVerbose) { @@ -164,29 +251,30 @@ final class RemoteFillService extends ServiceConnector.Impl<IAutoFillService> { } CompletableFuture<FillResponse> fillRequest = new CompletableFuture<>(); - remoteService.onFillCredentialRequest(request, new IFillCallback.Stub() { - @Override - public void onCancellable(ICancellationSignal cancellation) { - CompletableFuture<FillResponse> future = futureRef.get(); - if (future != null && future.isCancelled()) { - dispatchCancellationSignal(cancellation); - } else { - cancellationSink.set(cancellation); - } - } - - @Override - public void onSuccess(FillResponse response) { - fillRequest.complete(response); - } - - @Override - public void onFailure(int requestId, CharSequence message) { - String errorMessage = message == null ? "" : String.valueOf(message); - fillRequest.completeExceptionally( - new RuntimeException(errorMessage)); - } - }, autofillCallback); + remoteService.onFillCredentialRequest( + request, maybeWrapWithWeakReference(new IFillCallback.Stub() { + @Override + public void onCancellable(ICancellationSignal cancellation) { + CompletableFuture<FillResponse> future = futureRef.get(); + if (future != null && future.isCancelled()) { + dispatchCancellationSignal(cancellation); + } else { + cancellationSink.set(cancellation); + } + } + + @Override + public void onSuccess(FillResponse response) { + fillRequest.complete(response); + } + + @Override + public void onFailure(int requestId, CharSequence message) { + String errorMessage = message == null ? "" : String.valueOf(message); + fillRequest.completeExceptionally( + new RuntimeException(errorMessage)); + } + }), autofillCallback); return fillRequest; }).orTimeout(TIMEOUT_REMOTE_REQUEST_MILLIS, TimeUnit.MILLISECONDS); futureRef.set(connectThenFillRequest); @@ -235,29 +323,30 @@ final class RemoteFillService extends ServiceConnector.Impl<IAutoFillService> { } CompletableFuture<FillResponse> fillRequest = new CompletableFuture<>(); - remoteService.onFillRequest(request, new IFillCallback.Stub() { - @Override - public void onCancellable(ICancellationSignal cancellation) { - CompletableFuture<FillResponse> future = futureRef.get(); - if (future != null && future.isCancelled()) { - dispatchCancellationSignal(cancellation); - } else { - cancellationSink.set(cancellation); - } - } - - @Override - public void onSuccess(FillResponse response) { - fillRequest.complete(response); - } - - @Override - public void onFailure(int requestId, CharSequence message) { - String errorMessage = message == null ? "" : String.valueOf(message); - fillRequest.completeExceptionally( - new RuntimeException(errorMessage)); - } - }); + remoteService.onFillRequest( + request, maybeWrapWithWeakReference(new IFillCallback.Stub() { + @Override + public void onCancellable(ICancellationSignal cancellation) { + CompletableFuture<FillResponse> future = futureRef.get(); + if (future != null && future.isCancelled()) { + dispatchCancellationSignal(cancellation); + } else { + cancellationSink.set(cancellation); + } + } + + @Override + public void onSuccess(FillResponse response) { + fillRequest.complete(response); + } + + @Override + public void onFailure(int requestId, CharSequence message) { + String errorMessage = message == null ? "" : String.valueOf(message); + fillRequest.completeExceptionally( + new RuntimeException(errorMessage)); + } + })); return fillRequest; }).orTimeout(TIMEOUT_REMOTE_REQUEST_MILLIS, TimeUnit.MILLISECONDS); futureRef.set(connectThenFillRequest); @@ -294,7 +383,7 @@ final class RemoteFillService extends ServiceConnector.Impl<IAutoFillService> { if (sVerbose) Slog.v(TAG, "calling onSaveRequest()"); CompletableFuture<IntentSender> save = new CompletableFuture<>(); - service.onSaveRequest(request, new ISaveCallback.Stub() { + service.onSaveRequest(request, maybeWrapWithWeakReference(new ISaveCallback.Stub() { @Override public void onSuccess(IntentSender intentSender) { save.complete(intentSender); @@ -304,7 +393,7 @@ final class RemoteFillService extends ServiceConnector.Impl<IAutoFillService> { public void onFailure(CharSequence message) { save.completeExceptionally(new RuntimeException(String.valueOf(message))); } - }); + })); return save; }).orTimeout(TIMEOUT_REMOTE_REQUEST_MILLIS, TimeUnit.MILLISECONDS) .whenComplete((res, err) -> Handler.getMain().post(() -> { diff --git a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java index 42ab05fdd231..4d42f154a392 100644 --- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java +++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java @@ -58,11 +58,13 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; +import android.view.ViewTreeObserver; import android.view.Window; import android.view.WindowManager; import android.view.autofill.AutofillManager; import android.widget.ImageView; import android.widget.RemoteViews; +import android.widget.ScrollView; import android.widget.TextView; import com.android.internal.R; @@ -370,9 +372,23 @@ final class SaveUi { params.windowAnimations = R.style.AutofillSaveAnimation; params.setTrustedOverlay(); + ScrollView scrollView = view.findViewById(R.id.autofill_sheet_scroll_view); + + View divider = view.findViewById(R.id.autofill_sheet_divider); + + ViewTreeObserver observer = scrollView.getViewTreeObserver(); + observer.addOnGlobalLayoutListener(() -> adjustDividerVisibility(scrollView, divider)); + + scrollView.getViewTreeObserver() + .addOnScrollChangedListener(() -> adjustDividerVisibility(scrollView, divider)); show(); } + private void adjustDividerVisibility(ScrollView scrollView, View divider) { + boolean canScrollDown = scrollView.canScrollVertically(1); // 1 to check scrolling down + divider.setVisibility(canScrollDown ? View.VISIBLE : View.INVISIBLE); + } + private boolean applyCustomDescription(@NonNull Context context, @NonNull View saveUiView, @NonNull ValueFinder valueFinder, @NonNull SaveInfo info) { final CustomDescription customDescription = info.getCustomDescription(); diff --git a/services/backup/flags.aconfig b/services/backup/flags.aconfig index 549fa36597b7..4022e3378954 100644 --- a/services/backup/flags.aconfig +++ b/services/backup/flags.aconfig @@ -10,6 +10,15 @@ flag { } flag { + name: "enable_metrics_system_backup_agents" + namespace: "backup" + description: "Enable SystemBackupAgent to collect B&R agent metrics by passing an instance of " + "the logger to each BackupHelper." + bug: "296844513" + is_fixed_read_only: true +} + +flag { name: "enable_max_size_writes_to_pipes" namespace: "onboarding" description: "Enables the write buffer to pipes to be of maximum size." diff --git a/services/companion/java/com/android/server/companion/CompanionApplicationController.java b/services/companion/java/com/android/server/companion/CompanionApplicationController.java index c2d2468bbe44..586aa8aaae98 100644 --- a/services/companion/java/com/android/server/companion/CompanionApplicationController.java +++ b/services/companion/java/com/android/server/companion/CompanionApplicationController.java @@ -22,9 +22,11 @@ import android.annotation.SuppressLint; import android.annotation.UserIdInt; import android.companion.AssociationInfo; import android.companion.CompanionDeviceService; +import android.companion.DevicePresenceEvent; import android.content.ComponentName; import android.content.Context; import android.os.Handler; +import android.os.ParcelUuid; import android.util.Log; import android.util.Slog; import android.util.SparseArray; @@ -46,7 +48,8 @@ import java.util.Map; * the services, maintaining the connection (the binding), and invoking callback methods such as * {@link CompanionDeviceService#onDeviceAppeared(AssociationInfo)}, * {@link CompanionDeviceService#onDeviceDisappeared(AssociationInfo)} and - * {@link CompanionDeviceService#onDeviceEvent(AssociationInfo, int)} in the application process. + * {@link CompanionDeviceService#onDevicePresenceEvent(DevicePresenceEvent)} in the + * application process. * * <p> * The following is the list of the APIs provided by {@link CompanionApplicationController} (to be @@ -54,7 +57,7 @@ import java.util.Map; * <ul> * <li> {@link #bindCompanionApplication(int, String, boolean)} * <li> {@link #unbindCompanionApplication(int, String)} - * <li> {@link #notifyCompanionApplicationDeviceEvent(AssociationInfo, int)} (AssociationInfo, int)} + * <li> {@link #notifyCompanionApplicationDevicePresenceEvent(AssociationInfo, int)} * <li> {@link #isCompanionApplicationBound(int, String)} * <li> {@link #isRebindingCompanionApplicationScheduled(int, String)} * </ul> @@ -72,6 +75,7 @@ public class CompanionApplicationController { private final @NonNull Context mContext; private final @NonNull AssociationStore mAssociationStore; + private final @NonNull ObservableUuidStore mObservableUuidStore; private final @NonNull CompanionDevicePresenceMonitor mDevicePresenceMonitor; private final @NonNull CompanionServicesRegister mCompanionServicesRegister; @@ -82,9 +86,11 @@ public class CompanionApplicationController { private final @NonNull AndroidPackageMap<Boolean> mScheduledForRebindingCompanionApplications; CompanionApplicationController(Context context, AssociationStore associationStore, + ObservableUuidStore observableUuidStore, CompanionDevicePresenceMonitor companionDevicePresenceMonitor) { mContext = context; mAssociationStore = associationStore; + mObservableUuidStore = observableUuidStore; mDevicePresenceMonitor = companionDevicePresenceMonitor; mCompanionServicesRegister = new CompanionServicesRegister(); mBoundCompanionApplications = new AndroidPackageMap<>(); @@ -281,25 +287,50 @@ public class CompanionApplicationController { primaryServiceConnector.postOnDeviceDisappeared(association); } - void notifyCompanionApplicationDeviceEvent(AssociationInfo association, int event) { + void notifyCompanionApplicationDevicePresenceEvent(AssociationInfo association, int event) { final int userId = association.getUserId(); final String packageName = association.getPackageName(); final CompanionDeviceServiceConnector primaryServiceConnector = getPrimaryServiceConnector(userId, packageName); + final DevicePresenceEvent devicePresenceEvent = + new DevicePresenceEvent(association.getId(), event, null); if (primaryServiceConnector == null) { - Slog.e(TAG, "notifyCompanionApplicationDeviceEvent(): " + Slog.e(TAG, "notifyCompanionApplicationDevicePresenceEvent(): " + "u" + userId + "/" + packageName + " event=[ " + event + " ] is NOT bound."); Slog.e(TAG, "Stacktrace", new Throwable()); return; } - Slog.i(TAG, "Calling onDeviceEvent() to userId=[" + userId + "] package=[" + Slog.i(TAG, "Calling onDevicePresenceEvent() to userId=[" + userId + "] package=[" + packageName + "] associationId=[" + association.getId() - + "] state=[" + event + "]"); + + "] event=[" + event + "]"); - primaryServiceConnector.postOnDeviceEvent(association, event); + primaryServiceConnector.postOnDevicePresenceEvent(devicePresenceEvent); + } + + void notifyApplicationDevicePresenceEvent(ObservableUuid uuid, int event) { + final int userId = uuid.getUserId(); + final ParcelUuid parcelUuid = uuid.getUuid(); + final String packageName = uuid.getPackageName(); + final CompanionDeviceServiceConnector primaryServiceConnector = + getPrimaryServiceConnector(userId, packageName); + final DevicePresenceEvent devicePresenceEvent = + new DevicePresenceEvent(DevicePresenceEvent.NO_ASSOCIATION, event, parcelUuid); + + if (primaryServiceConnector == null) { + Slog.e(TAG, "notifyApplicationDevicePresenceChanged(): " + + "u" + userId + "/" + packageName + + " event=[ " + event + " ] is NOT bound."); + Slog.e(TAG, "Stacktrace", new Throwable()); + return; + } + + Slog.i(TAG, "Calling onDevicePresenceEvent() to userId=[" + userId + "] package=[" + + packageName + "]" + "event= [" + event + "]"); + + primaryServiceConnector.postOnDevicePresenceEvent(devicePresenceEvent); } void dump(@NonNull PrintWriter out) { @@ -364,6 +395,9 @@ public class CompanionApplicationController { // Make sure to clean up the state for all the associations // that associate with this package. boolean shouldScheduleRebind = false; + boolean shouldScheduleRebindForUuid = false; + final List<ObservableUuid> uuids = + mObservableUuidStore.getObservableUuidsForPackage(userId, packageName); for (AssociationInfo ai : mAssociationStore.getAssociationsForPackage(userId, packageName)) { @@ -385,7 +419,14 @@ public class CompanionApplicationController { } } - return stillAssociated && shouldScheduleRebind; + for (ObservableUuid uuid : uuids) { + if (mDevicePresenceMonitor.isDeviceUuidPresent(uuid.getUuid())) { + shouldScheduleRebindForUuid = true; + break; + } + } + + return (stillAssociated && shouldScheduleRebind) || shouldScheduleRebindForUuid; } private class CompanionServicesRegister extends PerUser<Map<String, List<ComponentName>>> { diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java index 50e18628852d..2e01ced2022b 100644 --- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java +++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java @@ -20,17 +20,17 @@ package com.android.server.companion; import static android.Manifest.permission.ASSOCIATE_COMPANION_DEVICES; import static android.Manifest.permission.DELIVER_COMPANION_MESSAGES; import static android.Manifest.permission.MANAGE_COMPANION_DEVICES; -import static android.Manifest.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE; import static android.Manifest.permission.REQUEST_COMPANION_PROFILE_AUTOMOTIVE_PROJECTION; +import static android.Manifest.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE; import static android.Manifest.permission.USE_COMPANION_TRANSPORTS; import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE; import static android.companion.AssociationRequest.DEVICE_PROFILE_AUTOMOTIVE_PROJECTION; -import static android.companion.CompanionDeviceService.DEVICE_EVENT_BLE_APPEARED; -import static android.companion.CompanionDeviceService.DEVICE_EVENT_BLE_DISAPPEARED; -import static android.companion.CompanionDeviceService.DEVICE_EVENT_BT_CONNECTED; -import static android.companion.CompanionDeviceService.DEVICE_EVENT_BT_DISCONNECTED; -import static android.companion.CompanionDeviceService.DEVICE_EVENT_SELF_MANAGED_APPEARED; -import static android.companion.CompanionDeviceService.DEVICE_EVENT_SELF_MANAGED_DISAPPEARED; +import static android.companion.DevicePresenceEvent.EVENT_BLE_APPEARED; +import static android.companion.DevicePresenceEvent.EVENT_BLE_DISAPPEARED; +import static android.companion.DevicePresenceEvent.EVENT_BT_CONNECTED; +import static android.companion.DevicePresenceEvent.EVENT_BT_DISCONNECTED; +import static android.companion.DevicePresenceEvent.EVENT_SELF_MANAGED_APPEARED; +import static android.companion.DevicePresenceEvent.EVENT_SELF_MANAGED_DISAPPEARED; import static android.content.pm.PackageManager.CERT_INPUT_SHA256; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.os.Process.SYSTEM_UID; @@ -45,6 +45,7 @@ import static com.android.server.companion.PackageUtils.enforceUsesCompanionDevi import static com.android.server.companion.PackageUtils.getPackageInfo; import static com.android.server.companion.PermissionsUtils.checkCallerCanManageCompanionDevice; import static com.android.server.companion.PermissionsUtils.enforceCallerCanManageAssociationsForPackage; +import static com.android.server.companion.PermissionsUtils.enforceCallerCanObservingDevicePresenceByUuid; import static com.android.server.companion.PermissionsUtils.enforceCallerIsSystemOr; import static com.android.server.companion.PermissionsUtils.enforceCallerIsSystemOrCanInteractWithUserId; import static com.android.server.companion.PermissionsUtils.sanitizeWithCallerChecks; @@ -75,6 +76,7 @@ import android.companion.IOnAssociationsChangedListener; import android.companion.IOnMessageReceivedListener; import android.companion.IOnTransportsChangedListener; import android.companion.ISystemDataTransferCallback; +import android.companion.ObservingDevicePresenceRequest; import android.companion.datatransfer.PermissionSyncRequest; import android.content.ComponentName; import android.content.Context; @@ -92,6 +94,7 @@ import android.os.Handler; import android.os.Message; import android.os.Parcel; import android.os.ParcelFileDescriptor; +import android.os.ParcelUuid; import android.os.PowerManagerInternal; import android.os.PowerWhitelistManager; import android.os.RemoteCallbackList; @@ -132,6 +135,7 @@ import java.io.File; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -221,6 +225,8 @@ public class CompanionDeviceManagerService extends SystemService { private CrossDeviceSyncController mCrossDeviceSyncController; + private ObservableUuidStore mObservableUuidStore; + public CompanionDeviceManagerService(Context context) { super(context); @@ -240,6 +246,7 @@ public class CompanionDeviceManagerService extends SystemService { mOnPackageVisibilityChangeListener = new OnPackageVisibilityChangeListener(mActivityManager); mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class); + mObservableUuidStore = new ObservableUuidStore(); } @Override @@ -247,24 +254,27 @@ public class CompanionDeviceManagerService extends SystemService { final Context context = getContext(); mPersistentStore = new PersistentDataStore(); + mAssociationRequestsProcessor = new AssociationRequestsProcessor( + /* cdmService */ this, mAssociationStore); + mBackupRestoreProcessor = new BackupRestoreProcessor( + /* cdmService */ this, mAssociationStore, mPersistentStore, + mSystemDataTransferRequestStore, mAssociationRequestsProcessor); loadAssociationsFromDisk(); + + mObservableUuidStore.getObservableUuidsForUser(getContext().getUserId()); + mAssociationStore.registerListener(mAssociationStoreChangeListener); mDevicePresenceMonitor = new CompanionDevicePresenceMonitor(mUserManager, - mAssociationStore, mDevicePresenceCallback); + mAssociationStore, mObservableUuidStore, mDevicePresenceCallback); - mAssociationRequestsProcessor = new AssociationRequestsProcessor( - /* cdmService */this, mAssociationStore); mCompanionAppController = new CompanionApplicationController( - context, mAssociationStore, mDevicePresenceMonitor); + context, mAssociationStore, mObservableUuidStore, mDevicePresenceMonitor); mTransportManager = new CompanionTransportManager(context, mAssociationStore); mSystemDataTransferProcessor = new SystemDataTransferProcessor(this, mPackageManagerInternal, mAssociationStore, mSystemDataTransferRequestStore, mTransportManager); - mBackupRestoreProcessor = new BackupRestoreProcessor( - /* cdmService */ this, mAssociationStore, mPersistentStore, - mSystemDataTransferRequestStore, mAssociationRequestsProcessor); // TODO(b/279663946): move context sync to a dedicated system service mCrossDeviceSyncController = new CrossDeviceSyncController(getContext(), mTransportManager); @@ -352,13 +362,29 @@ public class CompanionDeviceManagerService extends SystemService { final int userId = user.getUserIdentifier(); final Set<BluetoothDevice> blueToothDevices = mDevicePresenceMonitor.getPendingConnectedDevices().get(userId); + + final List<ObservableUuid> observableUuids = + mObservableUuidStore.getObservableUuidsForUser(userId); + if (blueToothDevices != null) { for (BluetoothDevice bluetoothDevice : blueToothDevices) { + final List<ParcelUuid> deviceUuids = bluetoothDevice.getUuids() == null + ? Collections.emptyList() : Arrays.asList(bluetoothDevice.getUuids()); + for (AssociationInfo ai: mAssociationStore.getAssociationsByAddress(bluetoothDevice.getAddress())) { Slog.i(TAG, "onUserUnlocked, device id( " + ai.getId() + " ) is connected"); mDevicePresenceMonitor.onBluetoothCompanionDeviceConnected(ai.getId()); } + + for (ObservableUuid observableUuid : observableUuids) { + if (deviceUuids.contains(observableUuid.getUuid())) { + Slog.i(TAG, "onUserUnlocked, UUID( " + + observableUuid.getUuid() + " ) is connected"); + mDevicePresenceMonitor.onDevicePresenceEventByUuid( + observableUuid, EVENT_BT_CONNECTED); + } + } } } } @@ -423,31 +449,31 @@ public class CompanionDeviceManagerService extends SystemService { } } - private void onDeviceEventInternal(int associationId, int event) { - Slog.i(TAG, "onDeviceEventInternal() id=" + associationId + " event= " + event); + private void onDevicePresenceEventInternal(int associationId, int event) { + Slog.i(TAG, "onDevicePresenceEventInternal() id=" + associationId + " event= " + event); final AssociationInfo association = mAssociationStore.getAssociationById(associationId); final String packageName = association.getPackageName(); final int userId = association.getUserId(); switch (event) { - case DEVICE_EVENT_BLE_APPEARED: - case DEVICE_EVENT_BT_CONNECTED: - case DEVICE_EVENT_SELF_MANAGED_APPEARED: + case EVENT_BLE_APPEARED: + case EVENT_BT_CONNECTED: + case EVENT_SELF_MANAGED_APPEARED: if (!association.shouldBindWhenPresent()) return; bindApplicationIfNeeded(association); - mCompanionAppController.notifyCompanionApplicationDeviceEvent( + mCompanionAppController.notifyCompanionApplicationDevicePresenceEvent( association, event); break; - case DEVICE_EVENT_BLE_DISAPPEARED: - case DEVICE_EVENT_BT_DISCONNECTED: - case DEVICE_EVENT_SELF_MANAGED_DISAPPEARED: + case EVENT_BLE_DISAPPEARED: + case EVENT_BT_DISCONNECTED: + case EVENT_SELF_MANAGED_DISAPPEARED: if (!mCompanionAppController.isCompanionApplicationBound(userId, packageName)) { if (DEBUG) Log.w(TAG, "u" + userId + "\\" + packageName + " is NOT bound"); return; } if (association.shouldBindWhenPresent()) { - mCompanionAppController.notifyCompanionApplicationDeviceEvent( + mCompanionAppController.notifyCompanionApplicationDevicePresenceEvent( association, event); } // Check if there are other devices associated to the app that are present. @@ -460,6 +486,45 @@ public class CompanionDeviceManagerService extends SystemService { } } + private void onDevicePresenceEventByUuidInternal(ObservableUuid uuid, int event) { + Slog.i(TAG, "onDevicePresenceEventByUuidInternal() id=" + uuid.getUuid() + + "for package=" + uuid.getPackageName() + " event=" + event); + final String packageName = uuid.getPackageName(); + final int userId = uuid.getUserId(); + + switch(event) { + case EVENT_BT_CONNECTED: + if (!mCompanionAppController.isCompanionApplicationBound(userId, packageName)) { + mCompanionAppController.bindCompanionApplication( + userId, packageName, /*bindImportant*/ false); + + } else if (DEBUG) { + Log.i(TAG, "u" + userId + "\\" + packageName + " is already bound"); + } + + mCompanionAppController.notifyApplicationDevicePresenceEvent(uuid, event); + + break; + case EVENT_BT_DISCONNECTED: + if (!mCompanionAppController.isCompanionApplicationBound(userId, packageName)) { + if (DEBUG) Log.w(TAG, "u" + userId + "\\" + packageName + " is NOT bound"); + return; + } + + mCompanionAppController.notifyApplicationDevicePresenceEvent(uuid, event); + // Check if there are other devices associated to the app or the UUID to be + // observed are present. + if (shouldBindPackage(userId, packageName)) return; + + mCompanionAppController.unbindCompanionApplication(userId, packageName); + + break; + default: + Slog.e(TAG, "Event: " + event + "is not supported"); + break; + } + } + private void bindApplicationIfNeeded(AssociationInfo association) { final String packageName = association.getPackageName(); final int userId = association.getUserId(); @@ -476,15 +541,26 @@ public class CompanionDeviceManagerService extends SystemService { /** * @return whether the package should be bound (i.e. at least one of the devices associated with - * the package is currently present). + * the package is currently present OR the UUID to be observed by this package is + * currently present). */ private boolean shouldBindPackage(@UserIdInt int userId, @NonNull String packageName) { final List<AssociationInfo> packageAssociations = mAssociationStore.getAssociationsForPackage(userId, packageName); + final List<ObservableUuid> observableUuids = + mObservableUuidStore.getObservableUuidsForPackage(userId, packageName); + for (AssociationInfo association : packageAssociations) { if (!association.shouldBindWhenPresent()) continue; if (mDevicePresenceMonitor.isDevicePresent(association.getId())) return true; } + + for (ObservableUuid uuid : observableUuids) { + if (mDevicePresenceMonitor.isDeviceUuidPresent(uuid.getUuid())) { + return true; + } + } + return false; } @@ -568,6 +644,8 @@ public class CompanionDeviceManagerService extends SystemService { // Clear associations. final List<AssociationInfo> associationsForPackage = mAssociationStore.getAssociationsForPackage(userId, packageName); + final List<ObservableUuid> uuidsTobeObserved = + mObservableUuidStore.getObservableUuidsForPackage(userId, packageName); for (AssociationInfo association : associationsForPackage) { mAssociationStore.removeAssociation(association.getId()); } @@ -575,6 +653,10 @@ public class CompanionDeviceManagerService extends SystemService { for (AssociationInfo association : associationsForPackage) { maybeRemoveRoleHolderForAssociation(association); } + // Clear the uuids to be observed. + for (ObservableUuid uuid : uuidsTobeObserved) { + mObservableUuidStore.removeObservableUuid(userId, uuid.getUuid(), packageName); + } mCompanionAppController.onPackagesChanged(userId); } @@ -855,6 +937,95 @@ public class CompanionDeviceManagerService extends SystemService { } @Override + @EnforcePermission(REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE) + public void startObservingDevicePresence(ObservingDevicePresenceRequest request, + String packageName, int userId) { + startObservingDevicePresence_enforcePermission(); + registerDevicePresenceListener(request, packageName, userId, /* active */ true); + } + + @Override + @EnforcePermission(REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE) + public void stopObservingDevicePresence(ObservingDevicePresenceRequest request, + String packageName, int userId) { + stopObservingDevicePresence_enforcePermission(); + registerDevicePresenceListener(request, packageName, userId, /* active */ false); + } + + private void registerDevicePresenceListener(ObservingDevicePresenceRequest request, + String packageName, int userId, boolean active) { + enforceUsesCompanionDeviceFeature(getContext(), userId, packageName); + enforceCallerIsSystemOr(userId, packageName); + + final int associationId = request.getAssociationId(); + final AssociationInfo associationInfo = mAssociationStore.getAssociationById( + associationId); + final ParcelUuid uuid = request.getUuid(); + + if (uuid != null) { + enforceCallerCanObservingDevicePresenceByUuid(getContext()); + if (active) { + startObservingDevicePresenceByUuid(uuid, packageName, userId); + } else { + stopObservingDevicePresenceByUuid(uuid, packageName, userId); + } + } else if (associationInfo == null) { + throw new IllegalArgumentException("App " + packageName + + " is not associated with device " + request.getAssociationId() + + " for user " + userId); + } else { + processDevicePresenceListener( + associationInfo, userId, packageName, active); + } + } + + private void startObservingDevicePresenceByUuid(ParcelUuid uuid, String packageName, + int userId) { + final List<ObservableUuid> observableUuids = + mObservableUuidStore.getObservableUuidsForPackage(userId, packageName); + + for (ObservableUuid observableUuid : observableUuids) { + if (observableUuid.getUuid().equals(uuid)) { + Slog.i(TAG, "The uuid: " + uuid + " for package:" + packageName + + "has been already scheduled for observing"); + return; + } + } + + final ObservableUuid observableUuid = new ObservableUuid(userId, uuid, + packageName, System.currentTimeMillis()); + + mObservableUuidStore.writeObservableUuid(userId, observableUuid); + } + + private void stopObservingDevicePresenceByUuid(ParcelUuid uuid, String packageName, + int userId) { + final List<ObservableUuid> uuidsTobeObserved = + mObservableUuidStore.getObservableUuidsForPackage(userId, packageName); + boolean isScheduledObserving = false; + + for (ObservableUuid observableUuid : uuidsTobeObserved) { + if (observableUuid.getUuid().equals(uuid)) { + isScheduledObserving = true; + break; + } + } + + if (!isScheduledObserving) { + Slog.i(TAG, "The uuid: " + uuid.toString() + " for package:" + packageName + + "has NOT been scheduled for observing yet"); + return; + } + + mObservableUuidStore.removeObservableUuid(userId, uuid, packageName); + mDevicePresenceMonitor.removeCurrentConnectedUuidDevice(uuid); + + if (!shouldBindPackage(userId, packageName)) { + mCompanionAppController.unbindCompanionApplication(userId, packageName); + } + } + + @Override public PendingIntent buildPermissionTransferUserConsentIntent(String packageName, int userId, int associationId) { return mSystemDataTransferProcessor.buildPermissionTransferUserConsentIntent( @@ -1002,6 +1173,11 @@ public class CompanionDeviceManagerService extends SystemService { + " for user " + userId)); } + processDevicePresenceListener(association, userId, packageName, active); + } + + private void processDevicePresenceListener(AssociationInfo association, + int userId, String packageName, boolean active) { // If already at specified state, then no-op. if (active == association.isNotifyOnDeviceNearby()) { if (DEBUG) Log.d(TAG, "Device presence listener is already at desired state."); @@ -1025,9 +1201,9 @@ public class CompanionDeviceManagerService extends SystemService { if (mDevicePresenceMonitor.isBlePresent(associationId) || mDevicePresenceMonitor.isSimulatePresent(associationId)) { onDeviceAppearedInternal(associationId); - onDeviceEventInternal(associationId, DEVICE_EVENT_BLE_APPEARED); + onDevicePresenceEventInternal(associationId, EVENT_BLE_APPEARED); } else if (mDevicePresenceMonitor.isBtConnected(associationId)) { - onDeviceEventInternal(associationId, DEVICE_EVENT_BT_CONNECTED); + onDevicePresenceEventInternal(associationId, EVENT_BT_CONNECTED); } } @@ -1518,20 +1694,25 @@ public class CompanionDeviceManagerService extends SystemService { private final CompanionDevicePresenceMonitor.Callback mDevicePresenceCallback = new CompanionDevicePresenceMonitor.Callback() { - @Override - public void onDeviceAppeared(int associationId) { - onDeviceAppearedInternal(associationId); - } + @Override + public void onDeviceAppeared(int associationId) { + onDeviceAppearedInternal(associationId); + } - @Override - public void onDeviceDisappeared(int associationId) { - onDeviceDisappearedInternal(associationId); - } + @Override + public void onDeviceDisappeared(int associationId) { + onDeviceDisappearedInternal(associationId); + } - @Override - public void onDeviceEvent(int associationId, int event) { - onDeviceEventInternal(associationId, event); - } + @Override + public void onDevicePresenceEvent(int associationId, int event) { + onDevicePresenceEventInternal(associationId, event); + } + + @Override + public void onDevicePresenceEventByUuid(ObservableUuid uuid, int event) { + onDevicePresenceEventByUuidInternal(uuid, event); + } }; private final PackageMonitor mPackageMonitor = new PackageMonitor() { diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceServiceConnector.java b/services/companion/java/com/android/server/companion/CompanionDeviceServiceConnector.java index 928842c79190..5abdb42b34fc 100644 --- a/services/companion/java/com/android/server/companion/CompanionDeviceServiceConnector.java +++ b/services/companion/java/com/android/server/companion/CompanionDeviceServiceConnector.java @@ -26,6 +26,7 @@ import android.annotation.SuppressLint; import android.annotation.UserIdInt; import android.companion.AssociationInfo; import android.companion.CompanionDeviceService; +import android.companion.DevicePresenceEvent; import android.companion.ICompanionDeviceService; import android.content.ComponentName; import android.content.Context; @@ -106,11 +107,10 @@ class CompanionDeviceServiceConnector extends ServiceConnector.Impl<ICompanionDe void postOnDeviceDisappeared(@NonNull AssociationInfo associationInfo) { post(companionService -> companionService.onDeviceDisappeared(associationInfo)); } - void postOnDeviceEvent(@NonNull AssociationInfo associationInfo, int event) { - post(companionService -> companionService.onDeviceEvent(associationInfo, event)); - } - + void postOnDevicePresenceEvent(@NonNull DevicePresenceEvent event) { + post(companionService -> companionService.onDevicePresenceEvent(event)); + } /** * Post "unbind" job, which will run *after* all previously posted jobs complete. diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java b/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java index e5a8c4fa22b7..5663434e2b6d 100644 --- a/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java +++ b/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java @@ -27,6 +27,7 @@ import android.companion.Telecom; import android.companion.datatransfer.PermissionSyncRequest; import android.net.MacAddress; import android.os.Binder; +import android.os.ParcelUuid; import android.os.ShellCommand; import android.util.Base64; import android.util.proto.ProtoOutputStream; @@ -80,6 +81,19 @@ class CompanionDeviceShellCommand extends ShellCommand { mDevicePresenceMonitor.simulateDeviceEvent(associationId, event); return 0; } + + if ("simulate-device-uuid-event".equals(cmd) && Flags.devicePresence()) { + String uuid = getNextArgRequired(); + String packageName = getNextArgRequired(); + int userId = getNextIntArgRequired(); + int event = getNextIntArgRequired(); + ObservableUuid observableUuid = new ObservableUuid( + userId, ParcelUuid.fromString(uuid), packageName, + System.currentTimeMillis()); + mDevicePresenceMonitor.simulateDeviceEventByUuid(observableUuid, event); + return 0; + } + switch (cmd) { case "list": { final int userId = getNextIntArgRequired(); @@ -447,6 +461,16 @@ class CompanionDeviceShellCommand extends ShellCommand { pw.println(" Case(3): "); pw.println(" Make CDM act as if the given companion device is BT disconnected "); pw.println(" USE FOR DEBUGGING AND/OR TESTING PURPOSES ONLY."); + + pw.println(" simulate-device-uuid-event UUID PACKAGE USERID EVENT"); + pw.println(" Simulate the companion device event changes:"); + pw.println(" Case(2): "); + pw.println(" Make CDM act as if the given DEVICE is BT connected base" + + "on the UUID"); + pw.println(" Case(3): "); + pw.println(" Make CDM act as if the given DEVICE is BT disconnected base" + + "on the UUID"); + pw.println(" USE FOR DEBUGGING AND/OR TESTING PURPOSES ONLY."); } pw.println(" remove-inactive-associations"); diff --git a/services/companion/java/com/android/server/companion/ObservableUuid.java b/services/companion/java/com/android/server/companion/ObservableUuid.java new file mode 100644 index 000000000000..6ab3188c8fd2 --- /dev/null +++ b/services/companion/java/com/android/server/companion/ObservableUuid.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.companion; + +import android.annotation.NonNull; +import android.annotation.UserIdInt; +import android.os.ParcelUuid; + +public class ObservableUuid { + private final int mUserId; + private final String mPackageName; + + private final ParcelUuid mUuid; + + private final long mTimeApprovedMs; + + public ObservableUuid(@UserIdInt int userId, @NonNull ParcelUuid uuid, + @NonNull String packageName, Long timeApprovedMs) { + mUserId = userId; + mUuid = uuid; + mPackageName = packageName; + mTimeApprovedMs = timeApprovedMs; + } + + public int getUserId() { + return mUserId; + } + + public ParcelUuid getUuid() { + return mUuid; + } + + public String getPackageName() { + return mPackageName; + } + + public long getTimeApprovedMs() { + return mTimeApprovedMs; + } +} diff --git a/services/companion/java/com/android/server/companion/ObservableUuidStore.java b/services/companion/java/com/android/server/companion/ObservableUuidStore.java new file mode 100644 index 000000000000..94be22afd9e2 --- /dev/null +++ b/services/companion/java/com/android/server/companion/ObservableUuidStore.java @@ -0,0 +1,295 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.companion; + +import static com.android.internal.util.XmlUtils.readIntAttribute; +import static com.android.internal.util.XmlUtils.readLongAttribute; +import static com.android.internal.util.XmlUtils.readStringAttribute; +import static com.android.internal.util.XmlUtils.writeIntAttribute; +import static com.android.internal.util.XmlUtils.writeLongAttribute; +import static com.android.internal.util.XmlUtils.writeStringAttribute; +import static com.android.server.companion.DataStoreUtils.createStorageFileForUser; +import static com.android.server.companion.DataStoreUtils.isEndOfTag; +import static com.android.server.companion.DataStoreUtils.isStartOfTag; +import static com.android.server.companion.DataStoreUtils.writeToFileSafely; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.UserIdInt; +import android.os.ParcelUuid; +import android.util.AtomicFile; +import android.util.Slog; +import android.util.SparseArray; +import android.util.Xml; + +import com.android.internal.annotations.GuardedBy; +import com.android.internal.util.XmlUtils; +import com.android.modules.utils.TypedXmlPullParser; +import com.android.modules.utils.TypedXmlSerializer; + +import org.xmlpull.v1.XmlPullParserException; + +import java.io.FileInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +public class ObservableUuidStore { + private static final String TAG = "CDM_ObservableUuidStore"; + private static final String FILE_NAME = "observing_uuids_presence.xml"; + private static final String XML_TAG_UUIDS = "uuids"; + private static final String XML_TAG_UUID = "uuid"; + private static final String XML_ATTR_UUID = "uuid"; + private static final String XML_ATTR_TIME_APPROVED = "time_approved"; + private static final String XML_ATTR_USER_ID = "user_id"; + private static final String XML_ATTR_PACKAGE = "package_name"; + private static final int READ_FROM_DISK_TIMEOUT = 5; // in seconds + + + private final ExecutorService mExecutor; + private final ConcurrentMap<Integer, AtomicFile> mUserIdToStorageFile = + new ConcurrentHashMap<>(); + + private final Object mLock = new Object(); + + @GuardedBy("mLock") + private final SparseArray<List<ObservableUuid>> mCachedPerUser = + new SparseArray<>(); + + public ObservableUuidStore() { + mExecutor = Executors.newSingleThreadExecutor(); + } + + /** + * Remove the observable uuid from the disk. + */ + void removeObservableUuid(@UserIdInt int userId, ParcelUuid uuid, String packageName) { + List<ObservableUuid> cachedObservableUuids; + + synchronized (mLock) { + // Remove requests from cache + cachedObservableUuids = readObservableUuidsFromCache(userId); + cachedObservableUuids.removeIf( + uuid1 -> uuid1.getPackageName().equals(packageName) + && uuid1.getUuid().equals(uuid)); + mCachedPerUser.set(userId, cachedObservableUuids); + } + // Remove requests from store + mExecutor.execute(() -> writeObservableUuidToStore(userId, cachedObservableUuids)); + } + + void writeObservableUuid(@UserIdInt int userId, ObservableUuid uuid) { + Slog.i(TAG, "Writing uuid=" + uuid.getUuid() + " to store."); + + List<ObservableUuid> cachedObservableUuids; + synchronized (mLock) { + // Write to cache + cachedObservableUuids = readObservableUuidsFromCache(userId); + cachedObservableUuids.removeIf(uuid1 -> uuid1.getUuid().equals( + uuid.getUuid()) && uuid1.getPackageName().equals(uuid.getPackageName())); + cachedObservableUuids.add(uuid); + mCachedPerUser.set(userId, cachedObservableUuids); + } + // Write to store + mExecutor.execute(() -> writeObservableUuidToStore(userId, cachedObservableUuids)); + } + + private void writeObservableUuidToStore(@UserIdInt int userId, + @NonNull List<ObservableUuid> cachedObservableUuids) { + final AtomicFile file = getStorageFileForUser(userId); + Slog.i(TAG, "Writing ObservableUuid for user " + userId + " to file=" + + file.getBaseFile().getPath()); + + // getStorageFileForUser() ALWAYS returns the SAME OBJECT, which allows us to synchronize + // accesses to the file on the file system using this AtomicFile object. + synchronized (file) { + writeToFileSafely(file, out -> { + final TypedXmlSerializer serializer = Xml.resolveSerializer(out); + serializer.setFeature( + "http://xmlpull.org/v1/doc/features.html#indent-output", true); + serializer.startDocument(null, true); + writeObservableUuidToXml(serializer, cachedObservableUuids); + serializer.endDocument(); + }); + } + } + + private void writeObservableUuidToXml(@NonNull TypedXmlSerializer serializer, + @Nullable Collection<ObservableUuid> uuids) throws IOException { + serializer.startTag(null, XML_TAG_UUIDS); + + for (ObservableUuid uuid : uuids) { + writeUuidToXml(serializer, uuid); + } + + serializer.endTag(null, XML_TAG_UUIDS); + } + + private void writeUuidToXml(@NonNull TypedXmlSerializer serializer, + @NonNull ObservableUuid uuid) throws IOException { + serializer.startTag(null, XML_TAG_UUID); + + writeIntAttribute(serializer, XML_ATTR_USER_ID, uuid.getUserId()); + writeStringAttribute(serializer, XML_ATTR_UUID, uuid.getUuid().toString()); + writeStringAttribute(serializer, XML_ATTR_PACKAGE, uuid.getPackageName()); + writeLongAttribute(serializer, XML_ATTR_TIME_APPROVED, uuid.getTimeApprovedMs()); + + serializer.endTag(null, XML_TAG_UUID); + } + + /** + * Read the observable UUIDs from the cache. + */ + @GuardedBy("mLock") + private List<ObservableUuid> readObservableUuidsFromCache(@UserIdInt int userId) { + List<ObservableUuid> cachedObservableUuids = mCachedPerUser.get(userId); + if (cachedObservableUuids == null) { + Future<List<ObservableUuid>> future = + mExecutor.submit(() -> readObservableUuidFromStore(userId)); + try { + cachedObservableUuids = future.get(READ_FROM_DISK_TIMEOUT, TimeUnit.SECONDS); + } catch (InterruptedException e) { + Slog.e(TAG, "Thread reading ObservableUuid from disk is " + + "interrupted."); + } catch (ExecutionException e) { + Slog.e(TAG, "Error occurred while reading ObservableUuid " + + "from disk."); + } catch (TimeoutException e) { + Slog.e(TAG, "Reading ObservableUuid from disk timed out."); + } + mCachedPerUser.set(userId, cachedObservableUuids); + } + return cachedObservableUuids; + } + + /** + * Reads previously persisted data for the given user + * + * @param userId Android UserID + * @return a list of ObservableUuid + */ + @NonNull + public List<ObservableUuid> readObservableUuidFromStore(@UserIdInt int userId) { + final AtomicFile file = getStorageFileForUser(userId); + Slog.i(TAG, "Reading ObservableUuid for user " + userId + " from " + + "file=" + file.getBaseFile().getPath()); + + // getStorageFileForUser() ALWAYS returns the SAME OBJECT, which allows us to synchronize + // accesses to the file on the file system using this AtomicFile object. + synchronized (file) { + if (!file.getBaseFile().exists()) { + Slog.d(TAG, "File does not exist -> Abort"); + return new ArrayList<>(); + } + try (FileInputStream in = file.openRead()) { + final TypedXmlPullParser parser = Xml.resolvePullParser(in); + XmlUtils.beginDocument(parser, XML_TAG_UUIDS); + + return readObservableUuidFromXml(parser); + } catch (XmlPullParserException | IOException e) { + Slog.e(TAG, "Error while reading requests file", e); + return new ArrayList<>(); + } + } + } + + @NonNull + private List<ObservableUuid> readObservableUuidFromXml( + @NonNull TypedXmlPullParser parser) throws XmlPullParserException, IOException { + if (!isStartOfTag(parser, XML_TAG_UUIDS)) { + throw new XmlPullParserException("The XML doesn't have start tag: " + XML_TAG_UUIDS); + } + + List<ObservableUuid> observableUuids = new ArrayList<>(); + + while (true) { + parser.nextTag(); + if (isEndOfTag(parser, XML_TAG_UUIDS)) { + break; + } + if (isStartOfTag(parser, XML_TAG_UUID)) { + observableUuids.add(readUuidFromXml(parser)); + } + } + + return observableUuids; + } + + private ObservableUuid readUuidFromXml(@NonNull TypedXmlPullParser parser) + throws XmlPullParserException, IOException { + if (!isStartOfTag(parser, XML_TAG_UUID)) { + throw new XmlPullParserException("XML doesn't have start tag: " + XML_TAG_UUID); + } + + final int userId = readIntAttribute(parser, XML_ATTR_USER_ID); + final ParcelUuid uuid = ParcelUuid.fromString(readStringAttribute(parser, XML_ATTR_UUID)); + final String packageName = readStringAttribute(parser, XML_ATTR_PACKAGE); + final Long timeApproved = readLongAttribute(parser, XML_ATTR_TIME_APPROVED); + + return new ObservableUuid(userId, uuid, packageName, timeApproved); + } + + /** + * Creates and caches {@link AtomicFile} object that represents the back-up file for the given + * user. + * <p> + * IMPORTANT: the method will ALWAYS return the same {@link AtomicFile} object, which makes it + * possible to synchronize reads and writes to the file using the returned object. + */ + @NonNull + private AtomicFile getStorageFileForUser(@UserIdInt int userId) { + return mUserIdToStorageFile.computeIfAbsent(userId, + u -> createStorageFileForUser(userId, FILE_NAME)); + } + + /** + * @return A list of ObservableUuids per package. + */ + public List<ObservableUuid> getObservableUuidsForPackage( + @UserIdInt int userId, @NonNull String packageName) { + final List<ObservableUuid> uuidsTobeObservedPerPackage = new ArrayList<>(); + synchronized (mLock) { + final List<ObservableUuid> uuids = readObservableUuidsFromCache(userId); + + for (ObservableUuid uuid : uuids) { + if (uuid.getPackageName().equals(packageName)) { + uuidsTobeObservedPerPackage.add(uuid); + } + } + } + + return uuidsTobeObservedPerPackage; + } + + /** + * @return A list of ObservableUuids per user. + */ + public List<ObservableUuid> getObservableUuidsForUser(@UserIdInt int userId) { + synchronized (mLock) { + return readObservableUuidsFromCache(userId); + } + } +} diff --git a/services/companion/java/com/android/server/companion/PermissionsUtils.java b/services/companion/java/com/android/server/companion/PermissionsUtils.java index f4e14df4de99..15bebbae05b1 100644 --- a/services/companion/java/com/android/server/companion/PermissionsUtils.java +++ b/services/companion/java/com/android/server/companion/PermissionsUtils.java @@ -19,6 +19,7 @@ package com.android.server.companion; import static android.Manifest.permission.INTERACT_ACROSS_USERS; import static android.Manifest.permission.MANAGE_COMPANION_DEVICES; import static android.Manifest.permission.REQUEST_COMPANION_SELF_MANAGED; +import static android.Manifest.permission.REQUEST_OBSERVE_DEVICE_UUID_PRESENCE; import static android.app.AppOpsManager.MODE_ALLOWED; import static android.companion.AssociationRequest.DEVICE_PROFILE_APP_STREAMING; import static android.companion.AssociationRequest.DEVICE_PROFILE_AUTOMOTIVE_PROJECTION; @@ -174,6 +175,14 @@ public final class PermissionsUtils { + " for u" + userId + "/" + packageName); } + static void enforceCallerCanObservingDevicePresenceByUuid(@NonNull Context context) { + if (context.checkCallingPermission(REQUEST_OBSERVE_DEVICE_UUID_PRESENCE) + != PERMISSION_GRANTED) { + throw new SecurityException("Caller (uid=" + getCallingUid() + ") does not have " + + "permissions to request observing device presence base on the UUID"); + } + } + /** * Check if the caller is either: * <ul> 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 6ba85bdda9e4..7eca1193ca12 100644 --- a/services/companion/java/com/android/server/companion/presence/BluetoothCompanionDeviceConnectionListener.java +++ b/services/companion/java/com/android/server/companion/presence/BluetoothCompanionDeviceConnectionListener.java @@ -16,6 +16,9 @@ package com.android.server.companion.presence; +import static android.companion.DevicePresenceEvent.EVENT_BT_CONNECTED; +import static android.companion.DevicePresenceEvent.EVENT_BT_DISCONNECTED; + import static com.android.server.companion.presence.CompanionDevicePresenceMonitor.DEBUG; import static com.android.server.companion.presence.Utils.btDeviceToString; @@ -27,6 +30,7 @@ import android.companion.AssociationInfo; import android.net.MacAddress; import android.os.Handler; import android.os.HandlerExecutor; +import android.os.ParcelUuid; import android.os.UserHandle; import android.os.UserManager; import android.util.Log; @@ -35,8 +39,11 @@ import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; import com.android.server.companion.AssociationStore; +import com.android.server.companion.ObservableUuid; +import com.android.server.companion.ObservableUuidStore; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -53,6 +60,8 @@ public class BluetoothCompanionDeviceConnectionListener void onBluetoothCompanionDeviceConnected(int associationId); void onBluetoothCompanionDeviceDisconnected(int associationId); + + void onDevicePresenceEventByUuid(ObservableUuid uuid, int event); } private final UserManager mUserManager; @@ -61,6 +70,8 @@ public class BluetoothCompanionDeviceConnectionListener /** A set of ALL connected BT device (not only companion.) */ private final @NonNull Map<MacAddress, BluetoothDevice> mAllConnectedDevices = new HashMap<>(); + private final @NonNull ObservableUuidStore mObservableUuidStore; + /** * A structure hold the connected BT devices that are pending to be reported to the companion * app when the user unlocks the local device per userId. @@ -70,8 +81,10 @@ public class BluetoothCompanionDeviceConnectionListener final SparseArray<Set<BluetoothDevice>> mPendingConnectedDevices = new SparseArray<>(); BluetoothCompanionDeviceConnectionListener(UserManager userManager, - @NonNull AssociationStore associationStore, @NonNull Callback callback) { + @NonNull AssociationStore associationStore, + @NonNull ObservableUuidStore observableUuidStore, @NonNull Callback callback) { mAssociationStore = associationStore; + mObservableUuidStore = observableUuidStore; mCallback = callback; mUserManager = userManager; } @@ -109,7 +122,6 @@ public class BluetoothCompanionDeviceConnectionListener bluetoothDevices.add(device); mPendingConnectedDevices.put(userId, bluetoothDevices); } - } else { onDeviceConnectivityChanged(device, true); } @@ -155,8 +167,13 @@ public class BluetoothCompanionDeviceConnectionListener } private void onDeviceConnectivityChanged(@NonNull BluetoothDevice device, boolean connected) { + int userId = UserHandle.myUserId(); final List<AssociationInfo> associations = mAssociationStore.getAssociationsByAddress(device.getAddress()); + final List<ObservableUuid> observableUuids = + mObservableUuidStore.getObservableUuidsForUser(userId); + final List<ParcelUuid> deviceUuids = device.getUuids() == null + ? Collections.emptyList() : Arrays.asList(device.getUuids()); if (DEBUG) { Log.d(TAG, "onDevice_ConnectivityChanged() " + btDeviceToString(device) @@ -177,6 +194,14 @@ public class BluetoothCompanionDeviceConnectionListener mCallback.onBluetoothCompanionDeviceDisconnected(id); } } + + for (ObservableUuid uuid : observableUuids) { + if (deviceUuids.contains(uuid.getUuid())) { + mCallback.onDevicePresenceEventByUuid( + uuid, connected ? EVENT_BT_CONNECTED + : EVENT_BT_DISCONNECTED); + } + } } @Override diff --git a/services/companion/java/com/android/server/companion/presence/CompanionDevicePresenceMonitor.java b/services/companion/java/com/android/server/companion/presence/CompanionDevicePresenceMonitor.java index e42b9356cca3..54a4692d964d 100644 --- a/services/companion/java/com/android/server/companion/presence/CompanionDevicePresenceMonitor.java +++ b/services/companion/java/com/android/server/companion/presence/CompanionDevicePresenceMonitor.java @@ -16,12 +16,12 @@ package com.android.server.companion.presence; -import static android.companion.CompanionDeviceService.DEVICE_EVENT_BLE_APPEARED; -import static android.companion.CompanionDeviceService.DEVICE_EVENT_BLE_DISAPPEARED; -import static android.companion.CompanionDeviceService.DEVICE_EVENT_BT_CONNECTED; -import static android.companion.CompanionDeviceService.DEVICE_EVENT_BT_DISCONNECTED; -import static android.companion.CompanionDeviceService.DEVICE_EVENT_SELF_MANAGED_APPEARED; -import static android.companion.CompanionDeviceService.DEVICE_EVENT_SELF_MANAGED_DISAPPEARED; +import static android.companion.DevicePresenceEvent.EVENT_BLE_APPEARED; +import static android.companion.DevicePresenceEvent.EVENT_BLE_DISAPPEARED; +import static android.companion.DevicePresenceEvent.EVENT_BT_CONNECTED; +import static android.companion.DevicePresenceEvent.EVENT_BT_DISCONNECTED; +import static android.companion.DevicePresenceEvent.EVENT_SELF_MANAGED_APPEARED; +import static android.companion.DevicePresenceEvent.EVENT_SELF_MANAGED_DISAPPEARED; import static android.os.Process.ROOT_UID; import static android.os.Process.SHELL_UID; @@ -36,12 +36,15 @@ import android.os.Binder; import android.os.Handler; import android.os.Looper; import android.os.Message; +import android.os.ParcelUuid; import android.os.UserManager; import android.util.Log; import android.util.Slog; import android.util.SparseArray; import com.android.server.companion.AssociationStore; +import com.android.server.companion.ObservableUuid; +import com.android.server.companion.ObservableUuidStore; import java.io.PrintWriter; import java.util.HashSet; @@ -61,7 +64,7 @@ import java.util.Set; * <li> {@link #isDevicePresent(int)} * <li> {@link Callback#onDeviceAppeared(int) Callback.onDeviceAppeared(int)} * <li> {@link Callback#onDeviceDisappeared(int) Callback.onDeviceDisappeared(int)} - * <li> {@link Callback#onDeviceStateChanged(int, int)}} + * <li> {@link Callback#onDevicePresenceEvent(int, int)}} * </ul> */ @SuppressLint("LongLogTag") @@ -78,11 +81,15 @@ public class CompanionDevicePresenceMonitor implements AssociationStore.OnChange /** Invoked when a companion device no longer seen nearby or disconnects. */ void onDeviceDisappeared(int associationId); - /**Invoked when device has corresponding event changes. */ - void onDeviceEvent(int associationId, int event); + /** Invoked when device has corresponding event changes. */ + void onDevicePresenceEvent(int associationId, int event); + + /** Invoked when device has corresponding event changes base on the UUID */ + void onDevicePresenceEventByUuid(ObservableUuid uuid, int event); } private final @NonNull AssociationStore mAssociationStore; + private final @NonNull ObservableUuidStore mObservableUuidStore; private final @NonNull Callback mCallback; private final @NonNull BluetoothCompanionDeviceConnectionListener mBtConnectionListener; private final @NonNull BleCompanionDeviceScanner mBleScanner; @@ -94,6 +101,7 @@ public class CompanionDevicePresenceMonitor implements AssociationStore.OnChange private final @NonNull Set<Integer> mConnectedBtDevices = new HashSet<>(); private final @NonNull Set<Integer> mNearbyBleDevices = new HashSet<>(); private final @NonNull Set<Integer> mReportedSelfManagedDevices = new HashSet<>(); + private final @NonNull Set<ParcelUuid> mConnectedUuidDevices = new HashSet<>(); // Tracking "simulated" presence. Used for debugging and testing only. private final @NonNull Set<Integer> mSimulated = new HashSet<>(); @@ -101,11 +109,14 @@ public class CompanionDevicePresenceMonitor implements AssociationStore.OnChange new SimulatedDevicePresenceSchedulerHelper(); public CompanionDevicePresenceMonitor(UserManager userManager, - @NonNull AssociationStore associationStore, @NonNull Callback callback) { + @NonNull AssociationStore associationStore, + @NonNull ObservableUuidStore observableUuidStore, @NonNull Callback callback) { mAssociationStore = associationStore; + mObservableUuidStore = observableUuidStore; mCallback = callback; mBtConnectionListener = new BluetoothCompanionDeviceConnectionListener(userManager, - associationStore, /* BluetoothCompanionDeviceConnectionListener.Callback */ this); + associationStore, mObservableUuidStore, + /* BluetoothCompanionDeviceConnectionListener.Callback */ this); mBleScanner = new BleCompanionDeviceScanner(associationStore, /* BleCompanionDeviceScanner.Callback */ this); } @@ -126,6 +137,20 @@ public class CompanionDevicePresenceMonitor implements AssociationStore.OnChange } /** + * @return current connected UUID devices. + */ + public Set<ParcelUuid> getCurrentConnectedUuidDevices() { + return mConnectedUuidDevices; + } + + /** + * Remove current connected UUID device. + */ + public void removeCurrentConnectedUuidDevice(ParcelUuid uuid) { + mConnectedUuidDevices.remove(uuid); + } + + /** * @return whether the associated companion devices is present. I.e. device is nearby (for BLE); * or devices is connected (for Bluetooth); or reported (by the application) to be * nearby (for "self-managed" associations). @@ -138,6 +163,13 @@ public class CompanionDevicePresenceMonitor implements AssociationStore.OnChange } /** + * @return whether the current uuid to be observed is present. + */ + public boolean isDeviceUuidPresent(ParcelUuid uuid) { + return mConnectedUuidDevices.contains(uuid); + } + + /** * @return whether the current device is BT connected and had already reported to the app. */ @@ -169,8 +201,8 @@ public class CompanionDevicePresenceMonitor implements AssociationStore.OnChange * {@link android.companion.CompanionDeviceManager#notifyDeviceAppeared(int) notifyDeviceAppeared()} */ public void onSelfManagedDeviceConnected(int associationId) { - onDeviceEvent(mReportedSelfManagedDevices, - associationId, DEVICE_EVENT_SELF_MANAGED_APPEARED); + onDevicePresenceEvent(mReportedSelfManagedDevices, + associationId, EVENT_SELF_MANAGED_APPEARED); } /** @@ -183,23 +215,23 @@ public class CompanionDevicePresenceMonitor implements AssociationStore.OnChange * {@link android.companion.CompanionDeviceManager#notifyDeviceDisappeared(int) notifyDeviceDisappeared()} */ public void onSelfManagedDeviceDisconnected(int associationId) { - onDeviceEvent(mReportedSelfManagedDevices, - associationId, DEVICE_EVENT_SELF_MANAGED_DISAPPEARED); + onDevicePresenceEvent(mReportedSelfManagedDevices, + associationId, EVENT_SELF_MANAGED_DISAPPEARED); } /** * Marks a "self-managed" device as disconnected when binderDied. */ public void onSelfManagedDeviceReporterBinderDied(int associationId) { - onDeviceEvent(mReportedSelfManagedDevices, - associationId, DEVICE_EVENT_SELF_MANAGED_DISAPPEARED); + onDevicePresenceEvent(mReportedSelfManagedDevices, + associationId, EVENT_SELF_MANAGED_DISAPPEARED); } @Override public void onBluetoothCompanionDeviceConnected(int associationId) { Slog.i(TAG, "onBluetoothCompanionDeviceConnected: " + "associationId( " + associationId + " )"); - onDeviceEvent(mConnectedBtDevices, associationId, DEVICE_EVENT_BT_CONNECTED); + onDevicePresenceEvent(mConnectedBtDevices, associationId, EVENT_BT_CONNECTED); // Stop scanning for BLE devices when this device is connected // and there are no other devices to connect to. if (canStopBleScan()) { @@ -214,22 +246,53 @@ public class CompanionDevicePresenceMonitor implements AssociationStore.OnChange // Start BLE scanning when the device is disconnected. mBleScanner.startScan(); - onDeviceEvent(mConnectedBtDevices, associationId, DEVICE_EVENT_BT_DISCONNECTED); + onDevicePresenceEvent(mConnectedBtDevices, associationId, EVENT_BT_DISCONNECTED); } @Override + public void onDevicePresenceEventByUuid(ObservableUuid uuid, int event) { + final ParcelUuid parcelUuid = uuid.getUuid(); + + switch(event) { + case EVENT_BT_CONNECTED: + boolean added = mConnectedUuidDevices.add(parcelUuid); + + if (!added) { + Slog.w(TAG, "Uuid= " + parcelUuid + "is ALREADY reported as " + + "present by this event=" + event); + } + + break; + case EVENT_BT_DISCONNECTED: + final boolean removed = mConnectedUuidDevices.remove(parcelUuid); + + if (!removed) { + Slog.w(TAG, "UUID= " + parcelUuid + " was NOT reported " + + "as present by this event= " + event); + + return; + } + + break; + } + + mCallback.onDevicePresenceEventByUuid(uuid, event); + } + + + @Override public void onBleCompanionDeviceFound(int associationId) { - onDeviceEvent(mNearbyBleDevices, associationId, DEVICE_EVENT_BLE_APPEARED); + onDevicePresenceEvent(mNearbyBleDevices, associationId, EVENT_BLE_APPEARED); } @Override public void onBleCompanionDeviceLost(int associationId) { - onDeviceEvent(mNearbyBleDevices, associationId, DEVICE_EVENT_BLE_DISAPPEARED); + onDevicePresenceEvent(mNearbyBleDevices, associationId, EVENT_BLE_DISAPPEARED); } /** FOR DEBUGGING AND/OR TESTING PURPOSES ONLY. */ @TestApi - public void simulateDeviceEvent(int associationId, int state) { + public void simulateDeviceEvent(int associationId, int event) { // IMPORTANT: this API should only be invoked via the // 'companiondevice simulate-device-appeared' Shell command, so the only uid-s allowed to // make this call are SHELL and ROOT. @@ -238,32 +301,43 @@ public class CompanionDevicePresenceMonitor implements AssociationStore.OnChange // Make sure the association exists. enforceAssociationExists(associationId); - switch (state) { - case DEVICE_EVENT_BLE_APPEARED: - simulateDeviceAppeared(associationId, state); + switch (event) { + case EVENT_BLE_APPEARED: + simulateDeviceAppeared(associationId, event); break; - case DEVICE_EVENT_BT_CONNECTED: + case EVENT_BT_CONNECTED: onBluetoothCompanionDeviceConnected(associationId); break; - case DEVICE_EVENT_BLE_DISAPPEARED: - simulateDeviceDisappeared(associationId, state); + case EVENT_BLE_DISAPPEARED: + simulateDeviceDisappeared(associationId, event); break; - case DEVICE_EVENT_BT_DISCONNECTED: + case EVENT_BT_DISCONNECTED: onBluetoothCompanionDeviceDisconnected(associationId); break; default: - throw new IllegalArgumentException("State: " + state + "is not supported"); + throw new IllegalArgumentException("Event: " + event + "is not supported"); } } + /** FOR DEBUGGING AND/OR TESTING PURPOSES ONLY. */ + @TestApi + public void simulateDeviceEventByUuid(ObservableUuid uuid, int event) { + // IMPORTANT: this API should only be invoked via the + // 'companiondevice simulate-device-uuid-events' Shell command, so the only uid-s allowed to + // make this call are SHELL and ROOT. + // No other caller (including SYSTEM!) should be allowed. + enforceCallerShellOrRoot(); + onDevicePresenceEventByUuid(uuid, event); + } + private void simulateDeviceAppeared(int associationId, int state) { - onDeviceEvent(mSimulated, associationId, state); + onDevicePresenceEvent(mSimulated, associationId, state); mSchedulerHelper.scheduleOnDeviceGoneCallForSimulatedDevicePresence(associationId); } private void simulateDeviceDisappeared(int associationId, int state) { mSchedulerHelper.unscheduleOnDeviceGoneCallForSimulatedDevicePresence(associationId); - onDeviceEvent(mSimulated, associationId, state); + onDevicePresenceEvent(mSimulated, associationId, state); } private void enforceAssociationExists(int associationId) { @@ -273,14 +347,14 @@ public class CompanionDevicePresenceMonitor implements AssociationStore.OnChange } } - private void onDeviceEvent(@NonNull Set<Integer> presentDevicesForSource, + private void onDevicePresenceEvent(@NonNull Set<Integer> presentDevicesForSource, int associationId, int event) { - Slog.i(TAG, "onDeviceEvent() id=" + associationId + ", state=" + event); + Slog.i(TAG, "onDevicePresenceEvent() id=" + associationId + ", event=" + event); switch (event) { - case DEVICE_EVENT_BLE_APPEARED: - case DEVICE_EVENT_BT_CONNECTED: - case DEVICE_EVENT_SELF_MANAGED_APPEARED: + case EVENT_BLE_APPEARED: + case EVENT_BT_CONNECTED: + case EVENT_SELF_MANAGED_APPEARED: final boolean added = presentDevicesForSource.add(associationId); if (!added) { @@ -292,9 +366,9 @@ public class CompanionDevicePresenceMonitor implements AssociationStore.OnChange mCallback.onDeviceAppeared(associationId); break; - case DEVICE_EVENT_BLE_DISAPPEARED: - case DEVICE_EVENT_BT_DISCONNECTED: - case DEVICE_EVENT_SELF_MANAGED_DISAPPEARED: + case EVENT_BLE_DISAPPEARED: + case EVENT_BT_DISCONNECTED: + case EVENT_SELF_MANAGED_DISAPPEARED: final boolean removed = presentDevicesForSource.remove(associationId); if (!removed) { @@ -312,7 +386,7 @@ public class CompanionDevicePresenceMonitor implements AssociationStore.OnChange return; } - mCallback.onDeviceEvent(associationId, event); + mCallback.onDevicePresenceEvent(associationId, event); } /** @@ -436,7 +510,7 @@ public class CompanionDevicePresenceMonitor implements AssociationStore.OnChange public void handleMessage(@NonNull Message msg) { final int associationId = msg.what; if (mSimulated.contains(associationId)) { - onDeviceEvent(mSimulated, associationId, DEVICE_EVENT_BLE_DISAPPEARED); + onDevicePresenceEvent(mSimulated, associationId, EVENT_BLE_DISAPPEARED); } } } diff --git a/services/core/Android.bp b/services/core/Android.bp index fdcd27da5bdc..3164e083af0f 100644 --- a/services/core/Android.bp +++ b/services/core/Android.bp @@ -211,6 +211,7 @@ java_library_static { "com_android_wm_shell_flags_lib", "com.android.server.utils_aconfig-java", "service-jobscheduler-deviceidle.flags-aconfig-java", + "backup_flags_lib", "policy_flags_lib", ], javac_shard_size: 50, diff --git a/services/core/java/com/android/server/SystemConfig.java b/services/core/java/com/android/server/SystemConfig.java index 3483c1a1404a..a493d7a57500 100644 --- a/services/core/java/com/android/server/SystemConfig.java +++ b/services/core/java/com/android/server/SystemConfig.java @@ -95,6 +95,7 @@ public class SystemConfig { private static final int ALLOW_OVERRIDE_APP_RESTRICTIONS = 0x100; private static final int ALLOW_IMPLICIT_BROADCASTS = 0x200; private static final int ALLOW_VENDOR_APEX = 0x400; + private static final int ALLOW_SIGNATURE_PERMISSIONS = 0x800; private static final int ALLOW_ALL = ~0; // property for runtime configuration differentiation @@ -597,7 +598,7 @@ public class SystemConfig { // Vendors are only allowed to customize these int vendorPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PRIVAPP_PERMISSIONS - | ALLOW_ASSOCIATIONS | ALLOW_VENDOR_APEX; + | ALLOW_SIGNATURE_PERMISSIONS | ALLOW_ASSOCIATIONS | ALLOW_VENDOR_APEX; if (Build.VERSION.DEVICE_INITIAL_SDK_INT <= Build.VERSION_CODES.O_MR1) { // For backward compatibility vendorPermissionFlag |= (ALLOW_PERMISSIONS | ALLOW_APP_CONFIGS); @@ -649,9 +650,9 @@ public class SystemConfig { // TODO(b/157203468): ALLOW_HIDDENAPI_WHITELISTING must be removed because we prohibited // the use of hidden APIs from the product partition. int productPermissionFlag = ALLOW_FEATURES | ALLOW_LIBS | ALLOW_PERMISSIONS - | ALLOW_APP_CONFIGS | ALLOW_PRIVAPP_PERMISSIONS | ALLOW_HIDDENAPI_WHITELISTING - | ALLOW_ASSOCIATIONS | ALLOW_OVERRIDE_APP_RESTRICTIONS | ALLOW_IMPLICIT_BROADCASTS - | ALLOW_VENDOR_APEX; + | ALLOW_APP_CONFIGS | ALLOW_PRIVAPP_PERMISSIONS | ALLOW_SIGNATURE_PERMISSIONS + | ALLOW_HIDDENAPI_WHITELISTING | ALLOW_ASSOCIATIONS + | ALLOW_OVERRIDE_APP_RESTRICTIONS | ALLOW_IMPLICIT_BROADCASTS | ALLOW_VENDOR_APEX; if (Build.VERSION.DEVICE_INITIAL_SDK_INT <= Build.VERSION_CODES.R) { // TODO(b/157393157): This must check product interface enforcement instead of // DEVICE_INITIAL_SDK_INT for the devices without product interface enforcement. @@ -772,6 +773,8 @@ public class SystemConfig { final boolean allowAppConfigs = (permissionFlag & ALLOW_APP_CONFIGS) != 0; final boolean allowPrivappPermissions = (permissionFlag & ALLOW_PRIVAPP_PERMISSIONS) != 0; + final boolean allowSignaturePermissions = (permissionFlag & ALLOW_SIGNATURE_PERMISSIONS) + != 0; final boolean allowOemPermissions = (permissionFlag & ALLOW_OEM_PERMISSIONS) != 0; final boolean allowApiWhitelisting = (permissionFlag & ALLOW_HIDDENAPI_WHITELISTING) != 0; @@ -1246,6 +1249,38 @@ public class SystemConfig { XmlUtils.skipCurrentTag(parser); } } break; + case "signature-permissions": { + if (allowSignaturePermissions) { + // signature permissions from system, apex, vendor, product and + // system_ext partitions are stored separately. This is to + // prevent xml files in the vendor partition from granting + // permissions to signature apps in the system partition and vice versa. + boolean vendor = permFile.toPath().startsWith( + Environment.getVendorDirectory().toPath() + "/") + || permFile.toPath().startsWith( + Environment.getOdmDirectory().toPath() + "/"); + boolean product = permFile.toPath().startsWith( + Environment.getProductDirectory().toPath() + "/"); + boolean systemExt = permFile.toPath().startsWith( + Environment.getSystemExtDirectory().toPath() + "/"); + if (vendor) { + readSignatureAppPermissions(parser, + mPermissionAllowlist.getVendorSignatureAppAllowlist()); + } else if (product) { + readSignatureAppPermissions(parser, + mPermissionAllowlist.getProductSignatureAppAllowlist()); + } else if (systemExt) { + readSignatureAppPermissions(parser, + mPermissionAllowlist.getSystemExtSignatureAppAllowlist()); + } else { + readSignatureAppPermissions(parser, + mPermissionAllowlist.getSignatureAppAllowlist()); + } + } else { + logNotAllowedInPartition(name, permFile, parser); + XmlUtils.skipCurrentTag(parser); + } + } break; case "oem-permissions": { if (allowOemPermissions) { readOemPermissions(parser); @@ -1655,6 +1690,12 @@ public class SystemConfig { readPermissionAllowlist(parser, allowlist, "privapp-permissions"); } + private void readSignatureAppPermissions(@NonNull XmlPullParser parser, + @NonNull ArrayMap<String, ArrayMap<String, Boolean>> allowlist) + throws IOException, XmlPullParserException { + readPermissionAllowlist(parser, allowlist, "signature-permissions"); + } + private void readInstallInUserType(XmlPullParser parser, Map<String, Set<String>> doInstallMap, Map<String, Set<String>> nonInstallMap) diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 9b1fade198fc..afb8345249b1 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -4491,6 +4491,12 @@ public final class ActiveServices { } } if (userId > 0) { + if (mAm.isSystemUserOnly(sInfo.flags)) { + Slog.w(TAG_SERVICE, service + " is only available for the SYSTEM user," + + " calling userId is: " + userId); + return null; + } + if (mAm.isSingleton(sInfo.processName, sInfo.applicationInfo, sInfo.name, sInfo.flags) && mAm.isValidSingletonCall(callingUid, sInfo.applicationInfo.uid)) { diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index c9bd0b4c4648..3de224addf95 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -4830,11 +4830,7 @@ public class ActivityManagerService extends IActivityManager.Stub if (!mConstants.mEnableWaitForFinishAttachApplication) { finishAttachApplicationInner(startSeq, callingUid, pid); } - - // Temporarily disable sending BOOT_COMPLETED to see if this was impacting perf tests - if (false) { - maybeSendBootCompletedLocked(app); - } + maybeSendBootCompletedLocked(app); } catch (Exception e) { // We need kill the process group here. (b/148588589) Slog.wtf(TAG, "Exception thrown during bind of " + app, e); @@ -13767,6 +13763,11 @@ public class ActivityManagerService extends IActivityManager.Stub return result; } + boolean isSystemUserOnly(int flags) { + return android.multiuser.Flags.enableSystemUserOnlyForServicesAndProviders() + && (flags & ServiceInfo.FLAG_SYSTEM_USER_ONLY) != 0; + } + /** * Checks to see if the caller is in the same app as the singleton * component, or the component is in a special app. It allows special apps diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java index c96c2ff4f2eb..3487ae3c6e6c 100644 --- a/services/core/java/com/android/server/am/BatteryStatsService.java +++ b/services/core/java/com/android/server/am/BatteryStatsService.java @@ -151,6 +151,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Properties; +import java.util.concurrent.CancellationException; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; @@ -653,7 +654,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub try { future.get(); return; - } catch (ExecutionException e) { + } catch (ExecutionException | CancellationException e) { return; } catch (InterruptedException e) { // Keep looping diff --git a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java index 2cac7a020005..db0f03f9edc6 100644 --- a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java +++ b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java @@ -1244,9 +1244,11 @@ class BroadcastQueueModernImpl extends BroadcastQueue { } private void deliveryTimeout(@NonNull BroadcastProcessQueue queue) { + final int cookie = traceBegin("deliveryTimeout"); synchronized (mService) { deliveryTimeoutLocked(queue); } + traceEnd(cookie); } private void deliveryTimeoutLocked(@NonNull BroadcastProcessQueue queue) { diff --git a/services/core/java/com/android/server/am/ContentProviderHelper.java b/services/core/java/com/android/server/am/ContentProviderHelper.java index 095d907d7df6..30f21a65b5b1 100644 --- a/services/core/java/com/android/server/am/ContentProviderHelper.java +++ b/services/core/java/com/android/server/am/ContentProviderHelper.java @@ -1249,9 +1249,9 @@ public class ContentProviderHelper { ProviderInfo cpi = providers.get(i); boolean singleton = mService.isSingleton(cpi.processName, cpi.applicationInfo, cpi.name, cpi.flags); - if (singleton && app.userId != UserHandle.USER_SYSTEM) { - // This is a singleton provider, but a user besides the - // default user is asking to initialize a process it runs + if (isSingletonOrSystemUserOnly(cpi) && app.userId != UserHandle.USER_SYSTEM) { + // This is a singleton or a SYSTEM user only provider, but a user besides the + // SYSTEM user is asking to initialize a process it runs // in... well, no, it doesn't actually run in this process, // it runs in the process of the default user. Get rid of it. providers.remove(i); @@ -1398,8 +1398,7 @@ public class ContentProviderHelper { final boolean processMatch = Objects.equals(pi.processName, app.processName) || pi.multiprocess; - final boolean userMatch = !mService.isSingleton( - pi.processName, pi.applicationInfo, pi.name, pi.flags) + final boolean userMatch = !isSingletonOrSystemUserOnly(pi) || app.userId == UserHandle.USER_SYSTEM; final boolean isInstantApp = pi.applicationInfo.isInstantApp(); final boolean splitInstalled = pi.splitName == null @@ -1985,4 +1984,13 @@ public class ContentProviderHelper { return isAuthRedirected; } } + + /** + * Returns true if Provider is either singleUser or systemUserOnly provider. + */ + private boolean isSingletonOrSystemUserOnly(ProviderInfo pi) { + return (android.multiuser.Flags.enableSystemUserOnlyForServicesAndProviders() + && mService.isSystemUserOnly(pi.flags)) + || mService.isSingleton(pi.processName, pi.applicationInfo, pi.name, pi.flags); + } } diff --git a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java index 9db5d0a99480..dc14c7aaa0b9 100644 --- a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java +++ b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java @@ -162,6 +162,7 @@ public class SettingsToPropertiesMapper { "pdf_viewer", "pixel_audio_android", "pixel_bluetooth", + "pixel_connectivity_gps", "pixel_system_sw_video", "pixel_watch", "platform_security", diff --git a/services/core/java/com/android/server/app/GameManagerService.java b/services/core/java/com/android/server/app/GameManagerService.java index 8b7e56ec410d..f6df60f736e8 100644 --- a/services/core/java/com/android/server/app/GameManagerService.java +++ b/services/core/java/com/android/server/app/GameManagerService.java @@ -28,6 +28,7 @@ import static com.android.internal.R.styleable.GameModeConfig_allowGameFpsOverri import static com.android.internal.R.styleable.GameModeConfig_supportsBatteryGameMode; import static com.android.internal.R.styleable.GameModeConfig_supportsPerformanceGameMode; import static com.android.internal.util.ConcurrentUtils.DIRECT_EXECUTOR; +import static com.android.server.wm.CompatScaleProvider.COMPAT_SCALE_MODE_GAME; import android.Manifest; import android.annotation.EnforcePermission; @@ -56,6 +57,7 @@ import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.UserInfo; +import android.content.res.CompatibilityInfo.CompatScale; import android.content.res.Resources; import android.content.res.TypedArray; import android.content.res.XmlResourceParser; @@ -76,6 +78,7 @@ import android.os.RemoteException; import android.os.ResultReceiver; import android.os.ShellCallback; import android.os.SystemProperties; +import android.os.UserHandle; import android.os.UserManager; import android.provider.DeviceConfig; import android.provider.DeviceConfig.Properties; @@ -97,6 +100,8 @@ import com.android.server.LocalServices; import com.android.server.ServiceThread; import com.android.server.SystemService; import com.android.server.SystemService.TargetUser; +import com.android.server.wm.ActivityTaskManagerInternal; +import com.android.server.wm.CompatScaleProvider; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -927,12 +932,24 @@ public final class GameManagerService extends IGameManagerService.Stub { } } - private final class LocalService extends GameManagerInternal { + private final class LocalService extends GameManagerInternal implements CompatScaleProvider { @Override public float getResolutionScalingFactor(String packageName, int userId) { final int gameMode = getGameModeFromSettingsUnchecked(packageName, userId); return getResolutionScalingFactorInternal(packageName, gameMode, userId); } + + @Nullable + @Override + public CompatScale getCompatScale(@NonNull String packageName, int uid) { + UserHandle userHandle = UserHandle.getUserHandleForUid(uid); + int userId = userHandle.getIdentifier(); + float scalingFactor = getResolutionScalingFactor(packageName, userId); + if (scalingFactor > 0) { + return new CompatScale(1f / scalingFactor); + } + return null; + } } /** @@ -2080,7 +2097,13 @@ public final class GameManagerService extends IGameManagerService.Stub { } private void publishLocalService() { - LocalServices.addService(GameManagerInternal.class, new LocalService()); + LocalService localService = new LocalService(); + + ActivityTaskManagerInternal atmi = + LocalServices.getService(ActivityTaskManagerInternal.class); + atmi.registerCompatScaleProvider(COMPAT_SCALE_MODE_GAME, localService); + + LocalServices.addService(GameManagerInternal.class, localService); } private void registerStatsCallbacks() { diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 4cbee2b89bb2..9f7c07e0af35 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -18,9 +18,6 @@ package com.android.server.audio; import static android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED; import static android.app.BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT; -import static android.media.audio.Flags.autoPublicVolumeApiHardening; -import static android.media.audio.Flags.automaticBtDeviceType; -import static android.media.audio.Flags.focusFreezeTestApi; import static android.media.AudioDeviceInfo.TYPE_BLE_HEADSET; import static android.media.AudioDeviceInfo.TYPE_BLE_SPEAKER; import static android.media.AudioDeviceInfo.TYPE_BLUETOOTH_A2DP; @@ -33,6 +30,9 @@ import static android.media.AudioManager.RINGER_MODE_NORMAL; import static android.media.AudioManager.RINGER_MODE_SILENT; import static android.media.AudioManager.RINGER_MODE_VIBRATE; import static android.media.AudioManager.STREAM_SYSTEM; +import static android.media.audio.Flags.autoPublicVolumeApiHardening; +import static android.media.audio.Flags.automaticBtDeviceType; +import static android.media.audio.Flags.focusFreezeTestApi; import static android.media.audiopolicy.Flags.enableFadeManagerConfiguration; import static android.os.Process.FIRST_APPLICATION_UID; import static android.os.Process.INVALID_UID; @@ -116,7 +116,6 @@ import android.media.AudioProfile; import android.media.AudioRecordingConfiguration; import android.media.AudioRoutesInfo; import android.media.AudioSystem; -import android.media.AudioTrack; import android.media.BluetoothProfileConnectionInfo; import android.media.FadeManagerConfiguration; import android.media.IAudioDeviceVolumeDispatcher; @@ -144,7 +143,7 @@ import android.media.IStrategyNonDefaultDevicesDispatcher; import android.media.IStrategyPreferredDevicesDispatcher; import android.media.IStreamAliasingDispatcher; import android.media.IVolumeController; -import android.media.LoudnessCodecConfigurator; +import android.media.LoudnessCodecController; import android.media.LoudnessCodecInfo; import android.media.MediaCodec; import android.media.MediaMetrics; @@ -10737,34 +10736,35 @@ public class AudioService extends IAudioService.Stub mLoudnessCodecHelper.unregisterLoudnessCodecUpdatesDispatcher(dispatcher); } - /** @see LoudnessCodecConfigurator#setAudioTrack(AudioTrack) */ + /** @see LoudnessCodecController#create(int) */ @Override - public void startLoudnessCodecUpdates(int piid, List<LoudnessCodecInfo> codecInfoList) { - mLoudnessCodecHelper.startLoudnessCodecUpdates(piid, codecInfoList); + public void startLoudnessCodecUpdates(int sessionId) { + mLoudnessCodecHelper.startLoudnessCodecUpdates(sessionId); } - /** @see LoudnessCodecConfigurator#setAudioTrack(AudioTrack) */ + /** @see LoudnessCodecController#release() */ @Override - public void stopLoudnessCodecUpdates(int piid) { - mLoudnessCodecHelper.stopLoudnessCodecUpdates(piid); + public void stopLoudnessCodecUpdates(int sessionId) { + mLoudnessCodecHelper.stopLoudnessCodecUpdates(sessionId); } - /** @see LoudnessCodecConfigurator#addMediaCodec(MediaCodec) */ + /** @see LoudnessCodecController#addMediaCodec(MediaCodec) */ @Override - public void addLoudnessCodecInfo(int piid, int mediaCodecHash, LoudnessCodecInfo codecInfo) { - mLoudnessCodecHelper.addLoudnessCodecInfo(piid, mediaCodecHash, codecInfo); + public void addLoudnessCodecInfo(int sessionId, int mediaCodecHash, + LoudnessCodecInfo codecInfo) { + mLoudnessCodecHelper.addLoudnessCodecInfo(sessionId, mediaCodecHash, codecInfo); } - /** @see LoudnessCodecConfigurator#removeMediaCodec(MediaCodec) */ + /** @see LoudnessCodecController#removeMediaCodec(MediaCodec) */ @Override - public void removeLoudnessCodecInfo(int piid, LoudnessCodecInfo codecInfo) { - mLoudnessCodecHelper.removeLoudnessCodecInfo(piid, codecInfo); + public void removeLoudnessCodecInfo(int sessionId, LoudnessCodecInfo codecInfo) { + mLoudnessCodecHelper.removeLoudnessCodecInfo(sessionId, codecInfo); } - /** @see LoudnessCodecConfigurator#getLoudnessCodecParams(AudioTrack, MediaCodec) */ + /** @see LoudnessCodecController#getLoudnessCodecParams(MediaCodec) */ @Override - public PersistableBundle getLoudnessParams(int piid, LoudnessCodecInfo codecInfo) { - return mLoudnessCodecHelper.getLoudnessParams(piid, codecInfo); + public PersistableBundle getLoudnessParams(LoudnessCodecInfo codecInfo) { + return mLoudnessCodecHelper.getLoudnessParams(codecInfo); } //========================================================================================== diff --git a/services/core/java/com/android/server/audio/LoudnessCodecHelper.java b/services/core/java/com/android/server/audio/LoudnessCodecHelper.java index 9b0afc4282a2..01f770b1e89f 100644 --- a/services/core/java/com/android/server/audio/LoudnessCodecHelper.java +++ b/services/core/java/com/android/server/audio/LoudnessCodecHelper.java @@ -30,6 +30,8 @@ import static android.media.audio.Flags.automaticBtDeviceType; import android.annotation.IntDef; import android.annotation.NonNull; +import android.media.AudioAttributes; +import android.media.AudioDeviceAttributes; import android.media.AudioDeviceInfo; import android.media.AudioManager.AudioDeviceCategory; import android.media.AudioPlaybackConfiguration; @@ -44,7 +46,6 @@ import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.SystemProperties; import android.util.Log; -import android.util.SparseArray; import android.util.SparseIntArray; import com.android.internal.annotations.GuardedBy; @@ -59,7 +60,9 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Objects; +import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; @@ -75,9 +78,9 @@ public class LoudnessCodecHelper { /** * Property containing a string to set for a custom built in speaker SPL range as defined by * CTA2075. The options that can be set are: - * - "small": for max SPL with test signal < 75 dB, - * - "medium": for max SPL with test signal between 70 and 90 dB, - * - "large": for max SPL with test signal > 85 dB. + * - "small": for max SPL with test signal < 75 dB, + * - "medium": for max SPL with test signal between 70 and 90 dB, + * - "large": for max SPL with test signal > 85 dB. */ private static final String SYSTEM_PROPERTY_SPEAKER_SPL_RANGE_SIZE = "audio.loudness.builtin-speaker-spl-range-size"; @@ -99,11 +102,13 @@ public class LoudnessCodecHelper { SPL_RANGE_LARGE }) @Retention(RetentionPolicy.SOURCE) - public @interface DeviceSplRange {} + public @interface DeviceSplRange { + } private static final class LoudnessRemoteCallbackList extends RemoteCallbackList<ILoudnessCodecUpdatesDispatcher> { private final LoudnessCodecHelper mLoudnessCodecHelper; + LoudnessRemoteCallbackList(LoudnessCodecHelper loudnessCodecHelper) { mLoudnessCodecHelper = loudnessCodecHelper; } @@ -133,9 +138,15 @@ public class LoudnessCodecHelper { private final Object mLock = new Object(); - /** Contains for each started piid the set corresponding to unique registered audio codecs. */ + /** Contains for each started track id the known started piids. */ + @GuardedBy("mLock") + private final HashMap<LoudnessTrackId, Set<Integer>> mStartedConfigPiids = + new HashMap<>(); + + /** Contains for each LoudnessTrackId a set of started coudec infos. */ @GuardedBy("mLock") - private final SparseArray<Set<LoudnessCodecInfo>> mStartedPiids = new SparseArray<>(); + private final HashMap<LoudnessTrackId, Set<LoudnessCodecInfo>> mStartedConfigInfo = + new HashMap<>(); /** Contains the current device id assignment for each piid. */ @GuardedBy("mLock") @@ -169,10 +180,12 @@ public class LoudnessCodecHelper { mMetadataType = metadataType; return this; } + Builder setIsDownmixing(boolean isDownmixing) { mIsDownmixing = isDownmixing; return this; } + Builder setDeviceSplRange(@DeviceSplRange int deviceSplRange) { mDeviceSplRange = deviceSplRange; return this; @@ -185,8 +198,8 @@ public class LoudnessCodecHelper { } private LoudnessCodecInputProperties(int metadataType, - boolean isDownmixing, - @DeviceSplRange int deviceSplRange) { + boolean isDownmixing, + @DeviceSplRange int deviceSplRange) { mMetadataType = metadataType; mIsDownmixing = isDownmixing; mDeviceSplRange = deviceSplRange; @@ -273,6 +286,50 @@ public class LoudnessCodecHelper { } } + /** + * Contains the properties necessary to identify the tracks that are receiving annotated + * loudness data. + **/ + @VisibleForTesting + static final class LoudnessTrackId { + private final int mSessionId; + + private final int mPid; + + private LoudnessTrackId(int sessionId, int pid) { + mSessionId = sessionId; + mPid = pid; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + // type check and cast + if (getClass() != obj.getClass()) { + return false; + } + final LoudnessTrackId lti = (LoudnessTrackId) obj; + return mSessionId == lti.mSessionId && mPid == lti.mPid; + } + + @Override + public int hashCode() { + return Objects.hash(mSessionId, mPid); + } + + @Override + public String toString() { + return "Loudness track id:" + + " session ID: " + mSessionId + + " pid: " + mPid; + } + } + @GuardedBy("mLock") private final HashMap<LoudnessCodecInputProperties, PersistableBundle> mCachedProperties = new HashMap<>(); @@ -290,120 +347,160 @@ public class LoudnessCodecHelper { mLoudnessUpdateDispatchers.unregister(dispatcher); } - void startLoudnessCodecUpdates(int piid, List<LoudnessCodecInfo> codecInfoList) { + void startLoudnessCodecUpdates(int sessionId) { + int pid = Binder.getCallingPid(); if (DEBUG) { - Log.d(TAG, "startLoudnessCodecUpdates: piid " + piid + " codecInfos " + codecInfoList); + Log.d(TAG, + "startLoudnessCodecUpdates: sessionId " + sessionId + " pid " + pid); } + final LoudnessTrackId newConfig = new LoudnessTrackId(sessionId, pid); + HashSet<Integer> newPiids; synchronized (mLock) { - if (mStartedPiids.contains(piid)) { - Log.w(TAG, "Already started loudness updates for piid " + piid); + if (mStartedConfigInfo.containsKey(newConfig)) { + Log.w(TAG, "Already started loudness updates for config: " + newConfig); return; } - Set<LoudnessCodecInfo> infoSet = new HashSet<>(codecInfoList); - mStartedPiids.put(piid, infoSet); - - int pid = Binder.getCallingPid(); - mPiidToPidCache.put(piid, pid); - sLogger.enqueue(LoudnessEvent.getStartPiid(piid, pid)); + mStartedConfigInfo.put(newConfig, new HashSet<>()); + newPiids = new HashSet<>(); + mStartedConfigPiids.put(newConfig, newPiids); } try (SafeCloseable ignored = ClearCallingIdentityContext.create()) { mAudioService.getActivePlaybackConfigurations().stream().filter( - conf -> conf.getPlayerInterfaceId() == piid).findFirst().ifPresent( - this::updateCodecParametersForConfiguration); + conf -> conf.getSessionId() == sessionId + && conf.getClientPid() == pid).forEach(apc -> { + int piid = apc.getPlayerInterfaceId(); + synchronized (mLock) { + newPiids.add(piid); + mPiidToPidCache.put(piid, pid); + sLogger.enqueue(LoudnessEvent.getStartPiid(piid, pid)); + } + }); } } - void stopLoudnessCodecUpdates(int piid) { + void stopLoudnessCodecUpdates(int sessionId) { + int pid = Binder.getCallingPid(); if (DEBUG) { - Log.d(TAG, "stopLoudnessCodecUpdates: piid " + piid); + Log.d(TAG, + "stopLoudnessCodecUpdates: sessionId " + sessionId + " pid " + pid); } + final LoudnessTrackId config = new LoudnessTrackId(sessionId, pid); synchronized (mLock) { - if (!mStartedPiids.contains(piid)) { - Log.w(TAG, "Loudness updates are already stopped for piid " + piid); + if (!mStartedConfigInfo.containsKey(config)) { + Log.w(TAG, "Loudness updates are already stopped config: " + config); return; } - mStartedPiids.remove(piid); - sLogger.enqueue(LoudnessEvent.getStopPiid(piid, mPiidToPidCache.get(piid, -1))); - mPiidToDeviceIdCache.delete(piid); - mPiidToPidCache.delete(piid); + final Set<Integer> startedPiidSet = mStartedConfigPiids.get(config); + if (startedPiidSet == null) { + Log.e(TAG, "Loudness updates are already stopped config: " + config); + return; + } + for (Integer piid : startedPiidSet) { + sLogger.enqueue(LoudnessEvent.getStopPiid(piid, mPiidToPidCache.get(piid, -1))); + mPiidToDeviceIdCache.delete(piid); + mPiidToPidCache.delete(piid); + } + mStartedConfigPiids.remove(config); + mStartedConfigInfo.remove(config); } } - void addLoudnessCodecInfo(int piid, int mediaCodecHash, LoudnessCodecInfo info) { + void addLoudnessCodecInfo(int sessionId, int mediaCodecHash, + LoudnessCodecInfo info) { + int pid = Binder.getCallingPid(); if (DEBUG) { - Log.d(TAG, "addLoudnessCodecInfo: piid " + piid + " mcHash " + mediaCodecHash + " info " - + info); + Log.d(TAG, "addLoudnessCodecInfo: sessionId " + sessionId + + " mcHash " + mediaCodecHash + " info " + info + " pid " + pid); } + final LoudnessTrackId config = new LoudnessTrackId(sessionId, pid); Set<LoudnessCodecInfo> infoSet; + Set<Integer> piids; synchronized (mLock) { - if (!mStartedPiids.contains(piid)) { - Log.w(TAG, "Cannot add new loudness info for stopped piid " + piid); + if (!mStartedConfigInfo.containsKey(config) || !mStartedConfigPiids.containsKey( + config)) { + Log.w(TAG, "Cannot add new loudness info for stopped config " + config); return; } - infoSet = mStartedPiids.get(piid); + piids = mStartedConfigPiids.get(config); + infoSet = mStartedConfigInfo.get(config); infoSet.add(info); } try (SafeCloseable ignored = ClearCallingIdentityContext.create()) { - mAudioService.getActivePlaybackConfigurations().stream().filter( - conf -> conf.getPlayerInterfaceId() == piid).findFirst().ifPresent( - apc -> { - final AudioDeviceInfo deviceInfo = apc.getAudioDeviceInfo(); - if (deviceInfo != null) { - PersistableBundle updateBundle = new PersistableBundle(); - synchronized (mLock) { - updateBundle.putPersistableBundle( - Integer.toString(mediaCodecHash), - getCodecBundle_l(deviceInfo, info)); - } - if (!updateBundle.isDefinitelyEmpty()) { - dispatchNewLoudnessParameters(piid, updateBundle); - } - } - }); + final PersistableBundle updateBundle = new PersistableBundle(); + Optional<AudioPlaybackConfiguration> apc = + mAudioService.getActivePlaybackConfigurations().stream().filter( + conf -> conf.getSessionId() == sessionId + && conf.getClientPid() == pid).findFirst(); + if (apc.isEmpty()) { + if (DEBUG) { + Log.d(TAG, + "No APCs found when adding loudness codec info. Using AudioAttributes" + + " routing for initial update"); + } + updateBundle.putPersistableBundle(Integer.toString(mediaCodecHash), + getLoudnessParams(info)); + } else { + final AudioDeviceInfo deviceInfo = apc.get().getAudioDeviceInfo(); + if (deviceInfo != null) { + synchronized (mLock) { + // found a piid that matches the configuration + piids.add(apc.get().getPlayerInterfaceId()); + + updateBundle.putPersistableBundle( + Integer.toString(mediaCodecHash), + getCodecBundle_l(deviceInfo.getInternalType(), + deviceInfo.getAddress(), info)); + } + } + } + if (!updateBundle.isDefinitelyEmpty()) { + dispatchNewLoudnessParameters(sessionId, updateBundle); + } } } - void removeLoudnessCodecInfo(int piid, LoudnessCodecInfo codecInfo) { + void removeLoudnessCodecInfo(int sessionId, LoudnessCodecInfo codecInfo) { if (DEBUG) { - Log.d(TAG, "removeLoudnessCodecInfo: piid " + piid + " info " + codecInfo); + Log.d(TAG, "removeLoudnessCodecInfo: session ID" + sessionId + " info " + codecInfo); } + + int pid = Binder.getCallingPid(); + final LoudnessTrackId config = new LoudnessTrackId(sessionId, pid); synchronized (mLock) { - if (!mStartedPiids.contains(piid)) { - Log.w(TAG, "Cannot remove loudness info for stopped piid " + piid); + if (!mStartedConfigInfo.containsKey(config) || !mStartedConfigPiids.containsKey( + config)) { + Log.w(TAG, "Cannot remove loudness info for stopped config " + config); return; } - final Set<LoudnessCodecInfo> infoSet = mStartedPiids.get(piid); - infoSet.remove(codecInfo); + final Set<LoudnessCodecInfo> codecInfos = mStartedConfigInfo.get(config); + if (!codecInfos.remove(codecInfo)) { + Log.w(TAG, "Could not find to remove codecInfo " + codecInfo); + } } } - PersistableBundle getLoudnessParams(int piid, LoudnessCodecInfo codecInfo) { + PersistableBundle getLoudnessParams(LoudnessCodecInfo codecInfo) { if (DEBUG) { - Log.d(TAG, "getLoudnessParams: piid " + piid + " codecInfo " + codecInfo); - } - try (SafeCloseable ignored = ClearCallingIdentityContext.create()) { - final List<AudioPlaybackConfiguration> configs = - mAudioService.getActivePlaybackConfigurations(); - - for (final AudioPlaybackConfiguration apc : configs) { - if (apc.getPlayerInterfaceId() == piid) { - final AudioDeviceInfo info = apc.getAudioDeviceInfo(); - if (info == null) { - Log.i(TAG, "Player with piid " + piid + " is not assigned any device"); - break; - } - synchronized (mLock) { - return getCodecBundle_l(info, codecInfo); - } - } + Log.d(TAG, "getLoudnessParams: codecInfo " + codecInfo); + } + final ArrayList<AudioDeviceAttributes> devicesForAttributes = + mAudioService.getDevicesForAttributesInt(new AudioAttributes.Builder() + .setUsage(AudioAttributes.USAGE_MEDIA) + .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) + .build(), /*forVolume=*/false); + if (!devicesForAttributes.isEmpty()) { + final AudioDeviceAttributes audioDeviceAttribute = devicesForAttributes.get(0); + synchronized (mLock) { + return getCodecBundle_l(audioDeviceAttribute.getInternalType(), + audioDeviceAttribute.getAddress(), codecInfo); } } @@ -444,13 +541,21 @@ public class LoudnessCodecHelper { continue; } mPiidToDeviceIdCache.put(piid, deviceInfo.getId()); - if (mStartedPiids.contains(piid)) { + final LoudnessTrackId config = new LoudnessTrackId(apc.getSessionId(), + apc.getClientPid()); + if (mStartedConfigInfo.containsKey(config) && mStartedConfigPiids.containsKey( + config)) { + if (DEBUG) { + Log.d(TAG, "Updating config: " + config + " with APC " + apc); + } updateApcList.add(apc); + // update the started piid set + mStartedConfigPiids.get(config).add(piid); } } } - updateApcList.forEach(apc -> updateCodecParametersForConfiguration(apc)); + updateApcList.forEach(this::updateCodecParametersForConfiguration); } /** Updates and dispatches the new loudness parameters for all its registered codecs. */ @@ -458,13 +563,18 @@ public class LoudnessCodecHelper { // Registered clients pw.println("\nRegistered clients:\n"); synchronized (mLock) { - for (int i = 0; i < mStartedPiids.size(); ++i) { - int piid = mStartedPiids.keyAt(i); - int pid = mPiidToPidCache.get(piid, -1); - final Set<LoudnessCodecInfo> codecInfos = mStartedPiids.get(piid); - pw.println(String.format("Player piid %d pid %d active codec types %s\n", piid, - pid, codecInfos.stream().map(Object::toString).collect( - Collectors.joining(", ")))); + for (Map.Entry<LoudnessTrackId, Set<Integer>> entry : mStartedConfigPiids.entrySet()) { + for (Integer piid : entry.getValue()) { + int pid = mPiidToPidCache.get(piid, -1); + final Set<LoudnessCodecInfo> codecInfos = mStartedConfigInfo.get( + entry.getKey()); + if (codecInfos != null) { + pw.println( + String.format("Player piid %d pid %d active codec types %s\n", piid, + pid, codecInfos.stream().map(Object::toString).collect( + Collectors.joining(", ")))); + } + } } pw.println(); } @@ -481,10 +591,12 @@ public class LoudnessCodecHelper { if (DEBUG) { Log.d(TAG, "Removing piid " + piid); } - mStartedPiids.delete(piid); mPiidToDeviceIdCache.delete(piid); } } + + mStartedConfigPiids.entrySet().removeIf(entry -> entry.getKey().mPid == pid); + mStartedConfigInfo.entrySet().removeIf(entry -> entry.getKey().mPid == pid); } } @@ -499,46 +611,55 @@ public class LoudnessCodecHelper { } final PersistableBundle allBundles = new PersistableBundle(); - final int piid = apc.getPlayerInterfaceId(); synchronized (mLock) { - final Set<LoudnessCodecInfo> codecInfos = mStartedPiids.get(piid); - + final LoudnessTrackId config = new LoudnessTrackId(apc.getSessionId(), + apc.getClientPid()); + final Set<LoudnessCodecInfo> codecInfos = mStartedConfigInfo.get(config); final AudioDeviceInfo deviceInfo = apc.getAudioDeviceInfo(); + if (codecInfos != null && deviceInfo != null) { for (LoudnessCodecInfo info : codecInfos) { - allBundles.putPersistableBundle(Integer.toString(info.hashCode()), - getCodecBundle_l(deviceInfo, info)); + if (info != null) { + allBundles.putPersistableBundle(Integer.toString(info.hashCode()), + getCodecBundle_l(deviceInfo.getInternalType(), + deviceInfo.getAddress(), info)); + } } } } if (!allBundles.isDefinitelyEmpty()) { - dispatchNewLoudnessParameters(piid, allBundles); + dispatchNewLoudnessParameters(apc.getSessionId(), allBundles); } } - private void dispatchNewLoudnessParameters(int piid, PersistableBundle bundle) { + private void dispatchNewLoudnessParameters(int sessionId, + PersistableBundle bundle) { if (DEBUG) { - Log.d(TAG, "dispatchNewLoudnessParameters: piid " + piid + " bundle: " + bundle); + Log.d(TAG, + "dispatchNewLoudnessParameters: sessionId " + sessionId + " bundle: " + bundle); } final int nbDispatchers = mLoudnessUpdateDispatchers.beginBroadcast(); for (int i = 0; i < nbDispatchers; ++i) { try { mLoudnessUpdateDispatchers.getBroadcastItem(i) - .dispatchLoudnessCodecParameterChange(piid, bundle); + .dispatchLoudnessCodecParameterChange(sessionId, bundle); } catch (RemoteException e) { - Log.e(TAG, "Error dispatching for piid: " + piid + " bundle: " + bundle , e); + Log.e(TAG, "Error dispatching for sessionId " + sessionId + " bundle: " + bundle, + e); } } mLoudnessUpdateDispatchers.finishBroadcast(); } @GuardedBy("mLock") - private PersistableBundle getCodecBundle_l(AudioDeviceInfo deviceInfo, - LoudnessCodecInfo codecInfo) { + private PersistableBundle getCodecBundle_l(int internalDeviceType, + String address, + LoudnessCodecInfo codecInfo) { LoudnessCodecInputProperties.Builder builder = new LoudnessCodecInputProperties.Builder(); - LoudnessCodecInputProperties prop = builder.setDeviceSplRange(getDeviceSplRange(deviceInfo)) + LoudnessCodecInputProperties prop = builder.setDeviceSplRange( + getDeviceSplRange(internalDeviceType, address)) .setIsDownmixing(codecInfo.isDownmixing) .setMetadataType(codecInfo.metadataType) .build(); @@ -552,14 +673,15 @@ public class LoudnessCodecHelper { } @DeviceSplRange - private int getDeviceSplRange(AudioDeviceInfo deviceInfo) { - final int internalDeviceType = deviceInfo.getInternalType(); - final @AudioDeviceCategory int deviceCategory; - if (automaticBtDeviceType()) { - deviceCategory = mAudioService.getBluetoothAudioDeviceCategory(deviceInfo.getAddress()); - } else { - deviceCategory = mAudioService.getBluetoothAudioDeviceCategory_legacy( - deviceInfo.getAddress(), AudioSystem.isBluetoothLeDevice(internalDeviceType)); + private int getDeviceSplRange(int internalDeviceType, String address) { + @AudioDeviceCategory int deviceCategory; + try (SafeCloseable ignored = ClearCallingIdentityContext.create()) { + if (automaticBtDeviceType()) { + deviceCategory = mAudioService.getBluetoothAudioDeviceCategory(address); + } else { + deviceCategory = mAudioService.getBluetoothAudioDeviceCategory_legacy( + address, AudioSystem.isBluetoothLeDevice(internalDeviceType)); + } } if (internalDeviceType == AudioSystem.DEVICE_OUT_SPEAKER) { final String splRange = SystemProperties.get( @@ -595,20 +717,28 @@ public class LoudnessCodecHelper { private static String splRangeToString(@DeviceSplRange int splRange) { switch (splRange) { - case SPL_RANGE_LARGE: return "large"; - case SPL_RANGE_MEDIUM: return "medium"; - case SPL_RANGE_SMALL: return "small"; - default: return "unknown"; + case SPL_RANGE_LARGE: + return "large"; + case SPL_RANGE_MEDIUM: + return "medium"; + case SPL_RANGE_SMALL: + return "small"; + default: + return "unknown"; } } @DeviceSplRange private static int stringToSplRange(String splRange) { switch (splRange) { - case "large": return SPL_RANGE_LARGE; - case "medium": return SPL_RANGE_MEDIUM; - case "small": return SPL_RANGE_SMALL; - default: return SPL_RANGE_UNKNOWN; + case "large": + return SPL_RANGE_LARGE; + case "medium": + return SPL_RANGE_MEDIUM; + case "small": + return SPL_RANGE_SMALL; + default: + return SPL_RANGE_UNKNOWN; } } } diff --git a/services/core/java/com/android/server/backup/SystemBackupAgent.java b/services/core/java/com/android/server/backup/SystemBackupAgent.java index de4979a0c826..5b9469bc5610 100644 --- a/services/core/java/com/android/server/backup/SystemBackupAgent.java +++ b/services/core/java/com/android/server/backup/SystemBackupAgent.java @@ -20,7 +20,8 @@ import android.app.IWallpaperManager; import android.app.backup.BackupAgentHelper; import android.app.backup.BackupAnnotations.BackupDestination; import android.app.backup.BackupDataInput; -import android.app.backup.BackupHelper; +import android.app.backup.BackupHelperWithLogger; +import android.app.backup.BackupRestoreEventLogger; import android.app.backup.FullBackup; import android.app.backup.FullBackupDataOutput; import android.app.backup.WallpaperBackupHelper; @@ -33,9 +34,10 @@ import android.os.ServiceManager; import android.os.UserHandle; import android.os.UserManager; import android.util.Slog; - import com.google.android.collect.Sets; +import com.android.server.backup.Flags; + import java.io.File; import java.io.IOException; import java.util.Set; @@ -107,10 +109,12 @@ public class SystemBackupAgent extends BackupAgentHelper { private int mUserId = UserHandle.USER_SYSTEM; private boolean mIsProfileUser = false; + private BackupRestoreEventLogger mLogger; @Override public void onCreate(UserHandle user, @BackupDestination int backupDestination) { super.onCreate(user, backupDestination); + mLogger = this.getBackupRestoreEventLogger(); mUserId = user.getIdentifier(); if (mUserId != UserHandle.USER_SYSTEM) { @@ -209,9 +213,12 @@ public class SystemBackupAgent extends BackupAgentHelper { } } - private void addHelperIfEligibleForUser(String keyPrefix, BackupHelper helper) { + private void addHelperIfEligibleForUser(String keyPrefix, BackupHelperWithLogger helper) { if (isHelperEligibleForUser(keyPrefix)) { addHelper(keyPrefix, helper); + if (Flags.enableMetricsSystemBackupAgents()) { + helper.setLogger(mLogger); + } } } diff --git a/services/core/java/com/android/server/biometrics/log/BiometricContext.java b/services/core/java/com/android/server/biometrics/log/BiometricContext.java index f8a98675c0c7..7f04628ff6de 100644 --- a/services/core/java/com/android/server/biometrics/log/BiometricContext.java +++ b/services/core/java/com/android/server/biometrics/log/BiometricContext.java @@ -87,10 +87,30 @@ public interface BiometricContext { * * @param context context that will be modified when changed * @param consumer callback when the context is modified + * + * @deprecated instead use {@link BiometricContext#subscribe(OperationContextExt, Consumer, + * Consumer, AuthenticateOptions)} + * TODO (b/294161627): Delete this API once Flags.DE_HIDL is removed. */ + @Deprecated void subscribe(@NonNull OperationContextExt context, @NonNull Consumer<OperationContext> consumer); + /** + * Subscribe to context changes and start the HAL operation. + * + * Note that this method only notifies for properties that are visible to the HAL. + * + * @param context context that will be modified when changed + * @param startHalConsumer callback to start HAL operation after subscription is done + * @param updateContextConsumer callback when the context is modified + * @param options authentication options for updating the context + */ + void subscribe(@NonNull OperationContextExt context, + @NonNull Consumer<OperationContext> startHalConsumer, + @NonNull Consumer<OperationContext> updateContextConsumer, + @Nullable AuthenticateOptions options); + /** Unsubscribe from context changes. */ void unsubscribe(@NonNull OperationContextExt context); diff --git a/services/core/java/com/android/server/biometrics/log/BiometricContextProvider.java b/services/core/java/com/android/server/biometrics/log/BiometricContextProvider.java index 535b7b743625..d8dfa60bdb51 100644 --- a/services/core/java/com/android/server/biometrics/log/BiometricContextProvider.java +++ b/services/core/java/com/android/server/biometrics/log/BiometricContextProvider.java @@ -238,6 +238,19 @@ public final class BiometricContextProvider implements BiometricContext { } @Override + public void subscribe(@NonNull OperationContextExt context, + @NonNull Consumer<OperationContext> startHalConsumer, + @NonNull Consumer<OperationContext> updateContextConsumer, + @Nullable AuthenticateOptions options) { + mSubscribers.put(updateContext(context, context.isCrypto()), updateContextConsumer); + if (options != null) { + startHalConsumer.accept(context.toAidlContext(options)); + } else { + startHalConsumer.accept(context.toAidlContext()); + } + } + + @Override public void unsubscribe(@NonNull OperationContextExt context) { mSubscribers.remove(context); } diff --git a/services/core/java/com/android/server/biometrics/log/OperationContextExt.java b/services/core/java/com/android/server/biometrics/log/OperationContextExt.java index 0045d44af9a1..da4e5154d49e 100644 --- a/services/core/java/com/android/server/biometrics/log/OperationContextExt.java +++ b/services/core/java/com/android/server/biometrics/log/OperationContextExt.java @@ -102,6 +102,24 @@ public class OperationContextExt { * @return the underlying AIDL context */ @NonNull + public OperationContext toAidlContext(@NonNull AuthenticateOptions options) { + if (options instanceof FaceAuthenticateOptions) { + return toAidlContext((FaceAuthenticateOptions) options); + } + if (options instanceof FingerprintAuthenticateOptions) { + return toAidlContext((FingerprintAuthenticateOptions) options); + } + throw new IllegalStateException("Authenticate options are invalid."); + } + + /** + * Gets the subset of the context that can be shared with the HAL and updates + * it with the given options. + * + * @param options authenticate options + * @return the underlying AIDL context + */ + @NonNull public OperationContext toAidlContext(@NonNull FaceAuthenticateOptions options) { mAidlContext.authenticateReason = AuthenticateReason .faceAuthenticateReason(getAuthReason(options)); diff --git a/services/core/java/com/android/server/biometrics/sensors/HalClientMonitor.java b/services/core/java/com/android/server/biometrics/sensors/HalClientMonitor.java index 0f01510bd908..b0649b90c466 100644 --- a/services/core/java/com/android/server/biometrics/sensors/HalClientMonitor.java +++ b/services/core/java/com/android/server/biometrics/sensors/HalClientMonitor.java @@ -22,6 +22,7 @@ import android.content.Context; import android.hardware.biometrics.BiometricAuthenticator; import android.os.IBinder; +import com.android.server.biometrics.Flags; import com.android.server.biometrics.log.BiometricContext; import com.android.server.biometrics.log.BiometricLogger; import com.android.server.biometrics.log.OperationContextExt; @@ -93,6 +94,9 @@ public abstract class HalClientMonitor<T> extends BaseClientMonitor { } protected OperationContextExt getOperationContext() { + if (Flags.deHidl()) { + return mOperationContext; + } return getBiometricContext().updateContext(mOperationContext, isCryptoOperation()); } 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 470dc4b7172c..22e399c6747b 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 @@ -37,6 +37,7 @@ import android.util.Slog; import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; +import com.android.server.biometrics.Flags; import com.android.server.biometrics.Utils; import com.android.server.biometrics.log.BiometricContext; import com.android.server.biometrics.log.BiometricLogger; @@ -153,7 +154,11 @@ public class FaceAuthenticationClient 0 /* vendorCode */); mCallback.onClientFinished(this, false /* success */); } else { - mCancellationSignal = doAuthenticate(); + if (Flags.deHidl()) { + startAuthenticate(); + } else { + mCancellationSignal = doAuthenticate(); + } } } catch (RemoteException e) { Slog.e(TAG, "Remote exception when requesting auth", e); @@ -182,6 +187,33 @@ public class FaceAuthenticationClient } } + private void startAuthenticate() throws RemoteException { + final AidlSession session = getFreshDaemon(); + + if (session.hasContextMethods()) { + final OperationContextExt opContext = getOperationContext(); + getBiometricContext().subscribe(opContext, ctx -> { + try { + mCancellationSignal = session.getSession().authenticateWithContext( + mOperationId, ctx); + } catch (RemoteException e) { + Slog.e(TAG, "Remote exception when requesting auth", e); + onError(BiometricFaceConstants.FACE_ERROR_HW_UNAVAILABLE, + 0 /* vendorCode */); + mCallback.onClientFinished(this, false /* success */); + } + }, ctx -> { + try { + session.getSession().onContextChanged(ctx); + } catch (RemoteException e) { + Slog.e(TAG, "Unable to notify context changed", e); + } + }, getOptions()); + } else { + mCancellationSignal = session.getSession().authenticate(mOperationId); + } + } + @Override protected void stopHalOperation() { unsubscribeBiometricContext(); 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 a529fb9779a7..5ddddda4e201 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 @@ -29,6 +29,7 @@ import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; import com.android.server.biometrics.BiometricsProto; +import com.android.server.biometrics.Flags; import com.android.server.biometrics.log.BiometricContext; import com.android.server.biometrics.log.BiometricLogger; import com.android.server.biometrics.log.OperationContextExt; @@ -111,7 +112,11 @@ public class FaceDetectClient extends AcquisitionClient<AidlSession> implements } try { - mCancellationSignal = doDetectInteraction(); + if (Flags.deHidl()) { + startDetect(); + } else { + mCancellationSignal = doDetectInteraction(); + } } catch (RemoteException e) { Slog.e(TAG, "Remote exception when requesting face detect", e); mCallback.onClientFinished(this, false /* success */); @@ -138,6 +143,30 @@ public class FaceDetectClient extends AcquisitionClient<AidlSession> implements } } + private void startDetect() throws RemoteException { + final AidlSession session = getFreshDaemon(); + + if (session.hasContextMethods()) { + final OperationContextExt opContext = getOperationContext(); + getBiometricContext().subscribe(opContext, ctx -> { + try { + mCancellationSignal = session.getSession().detectInteractionWithContext(ctx); + } catch (RemoteException e) { + Slog.e(TAG, "Remote exception when requesting face detect", e); + mCallback.onClientFinished(this, false /* success */); + } + }, ctx -> { + try { + session.getSession().onContextChanged(ctx); + } catch (RemoteException e) { + Slog.e(TAG, "Unable to notify context changed", e); + } + }, mOptions); + } else { + mCancellationSignal = session.getSession().detectInteraction(); + } + } + @Override public void onInteractionDetected() { vibrateSuccess(); diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java index 0af6e40434ef..f5c452992674 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java @@ -36,6 +36,7 @@ import android.util.Slog; import android.view.Surface; import com.android.internal.R; +import com.android.server.biometrics.Flags; import com.android.server.biometrics.HardwareAuthTokenUtils; import com.android.server.biometrics.Utils; import com.android.server.biometrics.log.BiometricContext; @@ -187,7 +188,11 @@ public class FaceEnrollClient extends EnrollClient<AidlSession> { features[i] = featureList.get(i); } - mCancellationSignal = doEnroll(features); + if (Flags.deHidl()) { + startEnroll(features); + } else { + mCancellationSignal = doEnroll(features); + } } catch (RemoteException | IllegalArgumentException e) { Slog.e(TAG, "Exception when requesting enroll", e); onError(BiometricFaceConstants.FACE_ERROR_UNABLE_TO_PROCESS, 0 /* vendorCode */); @@ -231,6 +236,48 @@ public class FaceEnrollClient extends EnrollClient<AidlSession> { } } + private void startEnroll(byte[] features) throws RemoteException { + final AidlSession session = getFreshDaemon(); + final HardwareAuthToken hat = + HardwareAuthTokenUtils.toHardwareAuthToken(mHardwareAuthToken); + + if (session.hasContextMethods()) { + final OperationContextExt opContext = getOperationContext(); + getBiometricContext().subscribe(opContext, ctx -> { + try { + if (session.supportsFaceEnrollOptions()) { + FaceEnrollOptions options = new FaceEnrollOptions(); + options.hardwareAuthToken = hat; + options.enrollmentType = EnrollmentType.DEFAULT; + options.features = features; + options.nativeHandlePreview = null; + options.context = ctx; + options.surfacePreview = mPreviewSurface; + mCancellationSignal = session.getSession().enrollWithOptions(options); + } else { + mCancellationSignal = session.getSession().enrollWithContext( + hat, EnrollmentType.DEFAULT, features, mHwPreviewHandle, ctx); + } + } catch (RemoteException e) { + Slog.e(TAG, "Exception when requesting enroll", e); + onError(BiometricFaceConstants.FACE_ERROR_UNABLE_TO_PROCESS, + 0 /* vendorCode */); + mCallback.onClientFinished(this, false /* success */); + } + }, ctx -> { + try { + session.getSession().onContextChanged(ctx); + } catch (RemoteException e) { + Slog.e(TAG, "Unable to notify context changed", e); + } + }, null /* options */); + } else { + mCancellationSignal = session.getSession().enroll(hat, EnrollmentType.DEFAULT, features, + mHwPreviewHandle); + } + } + + @Override protected void stopHalOperation() { unsubscribeBiometricContext(); diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java index 145885de5c32..f7e812330ece 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java @@ -44,6 +44,7 @@ import android.provider.Settings; import android.util.Slog; import com.android.internal.R; +import com.android.server.biometrics.Flags; import com.android.server.biometrics.log.BiometricContext; import com.android.server.biometrics.log.BiometricLogger; import com.android.server.biometrics.log.CallbackWithProbe; @@ -297,7 +298,11 @@ public class FingerprintAuthenticationClient } try { - mCancellationSignal = doAuthenticate(); + if (Flags.deHidl()) { + startAuthentication(); + } else { + mCancellationSignal = doAuthenticate(); + } } catch (RemoteException e) { Slog.e(TAG, "Remote exception", e); onError( @@ -353,6 +358,51 @@ public class FingerprintAuthenticationClient return cancel; } + private void startAuthentication() { + final AidlSession session = getFreshDaemon(); + final OperationContextExt opContext = getOperationContext(); + + getBiometricContext().subscribe(opContext, ctx -> { + try { + if (session.hasContextMethods()) { + mCancellationSignal = session.getSession().authenticateWithContext(mOperationId, + ctx); + } else { + mCancellationSignal = session.getSession().authenticate(mOperationId); + } + + if (getBiometricContext().isAwake()) { + mALSProbeCallback.getProbe().enable(); + } + } catch (RemoteException e) { + Slog.e(TAG, "Remote exception", e); + onError( + BiometricFingerprintConstants.FINGERPRINT_ERROR_HW_UNAVAILABLE, + 0 /* vendorCode */); + mSensorOverlays.hide(getSensorId()); + if (sidefpsControllerRefactor()) { + mAuthenticationStateListeners.onAuthenticationStopped(); + } + mCallback.onClientFinished(this, false /* success */); + } + }, ctx -> { + if (session.hasContextMethods()) { + try { + session.getSession().onContextChanged(ctx); + } catch (RemoteException e) { + Slog.e(TAG, "Unable to notify context changed", e); + } + } + + final boolean isAwake = getBiometricContext().isAwake(); + if (isAwake) { + mALSProbeCallback.getProbe().enable(); + } else { + mALSProbeCallback.getProbe().disable(); + } + }, getOptions()); + } + @Override protected void stopHalOperation() { mSensorOverlays.hide(getSensorId()); diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java index 3aab7b300a87..a7fb7741fee1 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java @@ -31,6 +31,7 @@ import android.os.RemoteException; import android.util.Slog; import com.android.server.biometrics.BiometricsProto; +import com.android.server.biometrics.Flags; import com.android.server.biometrics.log.BiometricContext; import com.android.server.biometrics.log.BiometricLogger; import com.android.server.biometrics.log.OperationContextExt; @@ -105,7 +106,11 @@ public class FingerprintDetectClient extends AcquisitionClient<AidlSession> this); try { - mCancellationSignal = doDetectInteraction(); + if (Flags.deHidl()) { + startDetectInteraction(); + } else { + mCancellationSignal = doDetectInteraction(); + } } catch (RemoteException e) { Slog.e(TAG, "Remote exception when requesting finger detect", e); mSensorOverlays.hide(getSensorId()); @@ -139,6 +144,32 @@ public class FingerprintDetectClient extends AcquisitionClient<AidlSession> } } + private void startDetectInteraction() throws RemoteException { + final AidlSession session = getFreshDaemon(); + + if (session.hasContextMethods()) { + final OperationContextExt opContext = getOperationContext(); + getBiometricContext().subscribe(opContext, ctx -> { + try { + mCancellationSignal = session.getSession().detectInteractionWithContext( + ctx); + } catch (RemoteException e) { + Slog.e(TAG, "Unable to start detect interaction", e); + mSensorOverlays.hide(getSensorId()); + mCallback.onClientFinished(this, false /* success */); + } + }, ctx -> { + try { + session.getSession().onContextChanged(ctx); + } catch (RemoteException e) { + Slog.e(TAG, "Unable to notify context changed", e); + } + }, mOptions); + } else { + mCancellationSignal = session.getSession().detectInteraction(); + } + } + @Override public void onInteractionDetected() { vibrateSuccess(); diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java index bf5011de1e59..3fb9223249b4 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java @@ -39,6 +39,7 @@ import android.os.RemoteException; import android.util.Slog; import android.view.accessibility.AccessibilityManager; +import com.android.server.biometrics.Flags; import com.android.server.biometrics.HardwareAuthTokenUtils; import com.android.server.biometrics.log.BiometricContext; import com.android.server.biometrics.log.BiometricLogger; @@ -200,7 +201,11 @@ public class FingerprintEnrollClient extends EnrollClient<AidlSession> implement BiometricNotificationUtils.cancelBadCalibrationNotification(getContext()); try { - mCancellationSignal = doEnroll(); + if (Flags.deHidl()) { + startEnroll(); + } else { + mCancellationSignal = doEnroll(); + } } catch (RemoteException e) { Slog.e(TAG, "Remote exception when requesting enroll", e); onError(BiometricFingerprintConstants.FINGERPRINT_ERROR_UNABLE_TO_PROCESS, @@ -237,6 +242,35 @@ public class FingerprintEnrollClient extends EnrollClient<AidlSession> implement } } + private void startEnroll() throws RemoteException { + final AidlSession session = getFreshDaemon(); + final HardwareAuthToken hat = + HardwareAuthTokenUtils.toHardwareAuthToken(mHardwareAuthToken); + + if (session.hasContextMethods()) { + final OperationContextExt opContext = getOperationContext(); + getBiometricContext().subscribe(opContext, ctx -> { + try { + mCancellationSignal = session.getSession().enrollWithContext( + hat, ctx); + } catch (RemoteException e) { + Slog.e(TAG, "Remote exception when requesting enroll", e); + onError(BiometricFingerprintConstants.FINGERPRINT_ERROR_UNABLE_TO_PROCESS, + 0 /* vendorCode */); + mCallback.onClientFinished(this, false /* success */); + } + }, ctx -> { + try { + session.getSession().onContextChanged(ctx); + } catch (RemoteException e) { + Slog.e(TAG, "Unable to notify context changed", e); + } + }, null /* options */); + } else { + mCancellationSignal = session.getSession().enroll(hat); + } + } + @Override protected void stopHalOperation() { mSensorOverlays.hide(getSensorId()); diff --git a/services/core/java/com/android/server/display/mode/DisplayModeDirector.java b/services/core/java/com/android/server/display/mode/DisplayModeDirector.java index 8707000ce962..82461fa647b3 100644 --- a/services/core/java/com/android/server/display/mode/DisplayModeDirector.java +++ b/services/core/java/com/android/server/display/mode/DisplayModeDirector.java @@ -388,6 +388,14 @@ public class DisplayModeDirector { boolean allowGroupSwitching = mModeSwitchingType == DisplayManager.SWITCHING_TYPE_ACROSS_AND_WITHIN_GROUPS; + // Some external displays physical refresh rate modes are slightly above 60hz. + // SurfaceFlinger will not enable these display modes unless it is configured to allow + // render rate at least at this frame rate. + if (mDisplayObserver.isExternalDisplayLocked(displayId)) { + primarySummary.maxRenderFrameRate = Math.max(baseMode.getRefreshRate(), + primarySummary.maxRenderFrameRate); + } + return new DesiredDisplayModeSpecs(baseMode.getModeId(), allowGroupSwitching, new RefreshRateRanges( @@ -1311,6 +1319,10 @@ public class DisplayModeDirector { updateUserSettingDisplayPreferredSize(displayInfo); } + boolean isExternalDisplayLocked(int displayId) { + return mExternalDisplaysConnected.contains(displayId); + } + @Nullable private DisplayInfo getDisplayInfo(int displayId) { DisplayInfo info = new DisplayInfo(); @@ -1419,7 +1431,7 @@ public class DisplayModeDirector { return; } synchronized (mLock) { - if (!mExternalDisplaysConnected.contains(displayId)) { + if (!isExternalDisplayLocked(displayId)) { return; } mExternalDisplaysConnected.remove(displayId); diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java index d34661d4d6ac..34e75c087864 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java @@ -47,6 +47,7 @@ import android.media.AudioDeviceInfo; import android.media.AudioProfile; import android.media.tv.TvInputInfo; import android.media.tv.TvInputManager.TvInputCallback; +import android.os.Handler; import android.util.Slog; import android.util.SparseBooleanArray; @@ -97,9 +98,15 @@ public final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { private boolean mSystemAudioMute = false; // If true, do not do routing control/send active source for internal source. - // Set to true when the device was woken up by <Text/Image View On>. + // Set to true for a short duration when the device is woken up by <Text/Image View On>. private boolean mSkipRoutingControl; + // Handler for posting a runnable to set `mSkipRoutingControl` to false after a delay + private final Handler mSkipRoutingControlHandler; + + // Runnable that sets `mSkipRoutingControl` to false + private final Runnable mResetSkipRoutingControlRunnable = () -> mSkipRoutingControl = false; + // Message buffer used to buffer selected messages to process later. <Active Source> // from a source device, for instance, needs to be buffered if the device is not // discovered yet. The buffered commands are taken out and when they are ready to @@ -162,6 +169,7 @@ public final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { HdmiControlManager.CEC_SETTING_NAME_SYSTEM_AUDIO_CONTROL) == HdmiControlManager.SYSTEM_AUDIO_CONTROL_ENABLED; mStandbyHandler = new HdmiCecStandbyModeHandler(service, this); + mSkipRoutingControlHandler = new Handler(service.getServiceLooper()); } @Override @@ -184,7 +192,14 @@ public final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { mService.getHdmiCecNetwork().addCecSwitch( mService.getHdmiCecNetwork().getPhysicalAddress()); // TV is a CEC switch too. mTvInputs.clear(); + mSkipRoutingControl = (reason == HdmiControlService.INITIATED_BY_WAKE_UP_MESSAGE); + mSkipRoutingControlHandler.removeCallbacks(mResetSkipRoutingControlRunnable); + if (mSkipRoutingControl) { + mSkipRoutingControlHandler.postDelayed(mResetSkipRoutingControlRunnable, + HdmiConfig.TIMEOUT_MS); + } + launchRoutingControl(reason != HdmiControlService.INITIATED_BY_ENABLE_CEC && reason != HdmiControlService.INITIATED_BY_BOOT_UP); resetSelectRequestBuffer(); diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java index bc7205ae2c07..67c23fc4db12 100644 --- a/services/core/java/com/android/server/input/InputManagerService.java +++ b/services/core/java/com/android/server/input/InputManagerService.java @@ -411,6 +411,40 @@ public class InputManagerService extends IInputManager.Stub private boolean mShowKeyPresses = false; private boolean mShowRotaryInput = false; + @GuardedBy("mLoadedPointerIconsByDisplayAndType") + final SparseArray<SparseArray<PointerIcon>> mLoadedPointerIconsByDisplayAndType = + new SparseArray<>(); + @GuardedBy("mLoadedPointerIconsByDisplayAndType") + boolean mUseLargePointerIcons = false; + + final DisplayManager.DisplayListener mDisplayListener = new DisplayManager.DisplayListener() { + @Override + public void onDisplayAdded(int displayId) { + + } + + @Override + public void onDisplayRemoved(int displayId) { + synchronized (mLoadedPointerIconsByDisplayAndType) { + mLoadedPointerIconsByDisplayAndType.remove(displayId); + } + } + + @Override + public void onDisplayChanged(int displayId) { + synchronized (mLoadedPointerIconsByDisplayAndType) { + // The display density could have changed, so force all cached pointer icons to be + // reloaded for the display. + var iconsByType = mLoadedPointerIconsByDisplayAndType.get(displayId); + if (iconsByType == null) { + return; + } + iconsByType.clear(); + } + mNative.reloadPointerIcons(); + } + }; + /** Point of injection for test dependencies. */ @VisibleForTesting static class Injector { @@ -578,6 +612,10 @@ public class InputManagerService extends IInputManager.Stub mWiredAccessoryCallbacks.systemReady(); } + Objects.requireNonNull( + mContext.getSystemService(DisplayManager.class)).registerDisplayListener( + mDisplayListener, mHandler); + mKeyboardLayoutManager.systemRunning(); mBatteryController.systemRunning(); mKeyboardBacklightController.systemRunning(); @@ -1292,6 +1330,8 @@ public class InputManagerService extends IInputManager.Stub updateAdditionalDisplayInputProperties(displayId, AdditionalDisplayInputProperties::reset); + // TODO(b/320763728): Rely on WindowInfosListener to determine when a display has been + // removed in InputDispatcher instead of this callback. mNative.displayRemoved(displayId); } @@ -1771,8 +1811,6 @@ public class InputManagerService extends IInputManager.Stub mPointerIconType = icon.getType(); mPointerIcon = mPointerIconType == PointerIcon.TYPE_CUSTOM ? icon : null; - if (!mCurrentDisplayProperties.pointerIconVisible) return false; - return mNative.setPointerIcon(icon, displayId, deviceId, pointerId, inputToken); } } @@ -2721,8 +2759,22 @@ public class InputManagerService extends IInputManager.Stub // Native callback. @SuppressWarnings("unused") - private PointerIcon getPointerIcon(int displayId) { - return PointerIcon.getDefaultIcon(getContextForPointerIcon(displayId)); + private @NonNull PointerIcon getLoadedPointerIcon(int displayId, int type) { + synchronized (mLoadedPointerIconsByDisplayAndType) { + SparseArray<PointerIcon> iconsByType = mLoadedPointerIconsByDisplayAndType.get( + displayId); + if (iconsByType == null) { + iconsByType = new SparseArray<>(); + mLoadedPointerIconsByDisplayAndType.put(displayId, iconsByType); + } + PointerIcon icon = iconsByType.get(type); + if (icon == null) { + icon = PointerIcon.getLoadedSystemIcon(getContextForPointerIcon(displayId), type, + mUseLargePointerIcons); + iconsByType.put(type, icon); + } + return Objects.requireNonNull(icon); + } } // Native callback. @@ -3423,6 +3475,10 @@ public class InputManagerService extends IInputManager.Stub private void applyAdditionalDisplayInputPropertiesLocked( AdditionalDisplayInputProperties properties) { // Handle changes to each of the individual properties. + // TODO(b/293587049): This approach for updating pointer display properties is only for when + // PointerChoreographer is disabled. Remove this logic when PointerChoreographer is + // permanently enabled. + if (properties.pointerIconVisible != mCurrentDisplayProperties.pointerIconVisible) { mCurrentDisplayProperties.pointerIconVisible = properties.pointerIconVisible; if (properties.pointerIconVisible) { @@ -3441,7 +3497,6 @@ public class InputManagerService extends IInputManager.Stub != mCurrentDisplayProperties.mousePointerAccelerationEnabled) { mCurrentDisplayProperties.mousePointerAccelerationEnabled = properties.mousePointerAccelerationEnabled; - mNative.setMousePointerAccelerationEnabled(properties.mousePointerAccelerationEnabled); } } @@ -3454,7 +3509,16 @@ public class InputManagerService extends IInputManager.Stub properties = new AdditionalDisplayInputProperties(); mAdditionalDisplayInputProperties.put(displayId, properties); } + final boolean oldPointerIconVisible = properties.pointerIconVisible; + final boolean oldMouseAccelerationEnabled = properties.mousePointerAccelerationEnabled; updater.accept(properties); + if (oldPointerIconVisible != properties.pointerIconVisible) { + mNative.setPointerIconVisibility(displayId, properties.pointerIconVisible); + } + if (oldMouseAccelerationEnabled != properties.mousePointerAccelerationEnabled) { + mNative.setMousePointerAccelerationEnabled(displayId, + properties.mousePointerAccelerationEnabled); + } if (properties.allDefaults()) { mAdditionalDisplayInputProperties.remove(displayId); } @@ -3556,6 +3620,18 @@ public class InputManagerService extends IInputManager.Stub mNative.setAccessibilityStickyKeysEnabled(enabled); } + void setUseLargePointerIcons(boolean useLargeIcons) { + synchronized (mLoadedPointerIconsByDisplayAndType) { + if (mUseLargePointerIcons == useLargeIcons) { + return; + } + mUseLargePointerIcons = useLargeIcons; + // Clear all cached icons on all displays. + mLoadedPointerIconsByDisplayAndType.clear(); + } + mNative.reloadPointerIcons(); + } + interface KeyboardBacklightControllerInterface { default void incrementKeyboardBacklight(int deviceId) {} default void decrementKeyboardBacklight(int deviceId) {} diff --git a/services/core/java/com/android/server/input/InputSettingsObserver.java b/services/core/java/com/android/server/input/InputSettingsObserver.java index be8d2a4d0bcb..bc55b24ce1eb 100644 --- a/services/core/java/com/android/server/input/InputSettingsObserver.java +++ b/services/core/java/com/android/server/input/InputSettingsObserver.java @@ -28,7 +28,6 @@ import android.os.UserHandle; import android.provider.DeviceConfig; import android.provider.Settings; import android.util.Log; -import android.view.PointerIcon; import android.view.ViewConfiguration; import java.util.Map; @@ -178,8 +177,7 @@ class InputSettingsObserver extends ContentObserver { final int accessibilityConfig = Settings.Secure.getIntForUser( mContext.getContentResolver(), Settings.Secure.ACCESSIBILITY_LARGE_POINTER_ICON, 0, UserHandle.USER_CURRENT); - PointerIcon.setUseLargeIcons(accessibilityConfig == 1); - mNative.reloadPointerIcons(); + mService.setUseLargePointerIcons(accessibilityConfig == 1); } private void updateLongPressTimeout(String reason) { diff --git a/services/core/java/com/android/server/input/NativeInputManagerService.java b/services/core/java/com/android/server/input/NativeInputManagerService.java index dd9204cd1401..6f5202029998 100644 --- a/services/core/java/com/android/server/input/NativeInputManagerService.java +++ b/services/core/java/com/android/server/input/NativeInputManagerService.java @@ -16,6 +16,7 @@ package com.android.server.input; +import android.annotation.NonNull; import android.annotation.Nullable; import android.hardware.display.DisplayViewport; import android.hardware.input.InputSensorInfo; @@ -118,7 +119,7 @@ interface NativeInputManagerService { void setPointerSpeed(int speed); - void setMousePointerAccelerationEnabled(boolean enabled); + void setMousePointerAccelerationEnabled(int displayId, boolean enabled); void setTouchpadPointerSpeed(int speed); @@ -184,10 +185,12 @@ interface NativeInputManagerService { void reloadPointerIcons(); - void setCustomPointerIcon(PointerIcon icon); + void setCustomPointerIcon(@NonNull PointerIcon icon); - boolean setPointerIcon(PointerIcon icon, int displayId, int deviceId, int pointerId, - IBinder inputToken); + boolean setPointerIcon(@NonNull PointerIcon icon, int displayId, int deviceId, int pointerId, + @NonNull IBinder inputToken); + + void setPointerIconVisibility(int displayId, boolean visible); void requestPointerCapture(IBinder windowToken, boolean enabled); @@ -351,7 +354,7 @@ interface NativeInputManagerService { public native void setPointerSpeed(int speed); @Override - public native void setMousePointerAccelerationEnabled(boolean enabled); + public native void setMousePointerAccelerationEnabled(int displayId, boolean enabled); @Override public native void setTouchpadPointerSpeed(int speed); @@ -451,6 +454,9 @@ interface NativeInputManagerService { int pointerId, IBinder inputToken); @Override + public native void setPointerIconVisibility(int displayId, boolean visible); + + @Override public native void requestPointerCapture(IBinder windowToken, boolean enabled); @Override diff --git a/services/core/java/com/android/server/inputmethod/AdditionalSubtypeUtils.java b/services/core/java/com/android/server/inputmethod/AdditionalSubtypeUtils.java index c76ca2beda96..fba71fd0ff9e 100644 --- a/services/core/java/com/android/server/inputmethod/AdditionalSubtypeUtils.java +++ b/services/core/java/com/android/server/inputmethod/AdditionalSubtypeUtils.java @@ -114,7 +114,7 @@ final class AdditionalSubtypeUtils { * @param userId The user ID to be associated with. */ static void save(ArrayMap<String, List<InputMethodSubtype>> allSubtypes, - ArrayMap<String, InputMethodInfo> methodMap, @UserIdInt int userId) { + InputMethodMap methodMap, @UserIdInt int userId) { final File inputMethodDir = getInputMethodDir(userId); if (allSubtypes.isEmpty()) { @@ -143,7 +143,7 @@ final class AdditionalSubtypeUtils { @VisibleForTesting static void saveToFile(ArrayMap<String, List<InputMethodSubtype>> allSubtypes, - ArrayMap<String, InputMethodInfo> methodMap, AtomicFile subtypesFile) { + InputMethodMap methodMap, AtomicFile subtypesFile) { // Safety net for the case that this function is called before methodMap is set. final boolean isSetMethodMap = methodMap != null && methodMap.size() > 0; FileOutputStream fos = null; diff --git a/services/core/java/com/android/server/inputmethod/HardwareKeyboardShortcutController.java b/services/core/java/com/android/server/inputmethod/HardwareKeyboardShortcutController.java index ad27c5252cbe..62adb25954b4 100644 --- a/services/core/java/com/android/server/inputmethod/HardwareKeyboardShortcutController.java +++ b/services/core/java/com/android/server/inputmethod/HardwareKeyboardShortcutController.java @@ -20,7 +20,6 @@ import android.annotation.AnyThread; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; -import android.util.ArrayMap; import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodSubtype; @@ -44,22 +43,23 @@ final class HardwareKeyboardShortcutController { return mUserId; } - HardwareKeyboardShortcutController( - @NonNull ArrayMap<String, InputMethodInfo> methodMap, @UserIdInt int userId) { + HardwareKeyboardShortcutController(@NonNull InputMethodMap methodMap, @UserIdInt int userId) { mUserId = userId; reset(methodMap); } @GuardedBy("ImfLock.class") - void reset(@NonNull ArrayMap<String, InputMethodInfo> methodMap) { + void reset(@NonNull InputMethodMap methodMap) { mSubtypeHandles.clear(); - final InputMethodSettings settings = new InputMethodSettings(methodMap, mUserId); - for (final InputMethodInfo imi : settings.getEnabledInputMethodListLocked()) { + final InputMethodSettings settings = InputMethodSettings.create(methodMap, mUserId); + final List<InputMethodInfo> inputMethods = settings.getEnabledInputMethodList(); + for (int i = 0; i < inputMethods.size(); ++i) { + final InputMethodInfo imi = inputMethods.get(i); if (!imi.shouldShowInInputMethodPicker()) { continue; } final List<InputMethodSubtype> subtypes = - settings.getEnabledInputMethodSubtypeListLocked(imi, true); + settings.getEnabledInputMethodSubtypeList(imi, true); if (subtypes.isEmpty()) { mSubtypeHandles.add(InputMethodSubtypeHandle.of(imi, null)); } else { diff --git a/services/core/java/com/android/server/inputmethod/InputMethodInfoUtils.java b/services/core/java/com/android/server/inputmethod/InputMethodInfoUtils.java index a7632519b7bc..6339686629f5 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodInfoUtils.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodInfoUtils.java @@ -23,7 +23,6 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; import android.text.TextUtils; -import android.util.ArrayMap; import android.util.Slog; import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodSubtype; @@ -46,7 +45,7 @@ final class InputMethodInfoUtils { private static final String TAG = "InputMethodInfoUtils"; /** - * Used in {@link #getFallbackLocaleForDefaultIme(ArrayList, Context)} to find the fallback IMEs + * Used in {@link #getFallbackLocaleForDefaultIme(List, Context)} to find the fallback IMEs * that are mainly used until the system becomes ready. Note that {@link Locale} in this array * is checked with {@link Locale#equals(Object)}, which means that {@code Locale.ENGLISH} * doesn't automatically match {@code Locale("en", "IN")}. @@ -64,7 +63,7 @@ final class InputMethodInfoUtils { @NonNull private final LinkedHashSet<InputMethodInfo> mInputMethodSet = new LinkedHashSet<>(); - InputMethodListBuilder fillImes(ArrayList<InputMethodInfo> imis, Context context, + InputMethodListBuilder fillImes(List<InputMethodInfo> imis, Context context, boolean checkDefaultAttribute, @Nullable Locale locale, boolean checkCountry, String requiredSubtypeMode) { for (int i = 0; i < imis.size(); ++i) { @@ -77,7 +76,7 @@ final class InputMethodInfoUtils { return this; } - InputMethodListBuilder fillAuxiliaryImes(ArrayList<InputMethodInfo> imis, Context context) { + InputMethodListBuilder fillAuxiliaryImes(List<InputMethodInfo> imis, Context context) { // If one or more auxiliary input methods are available, OK to stop populating the list. for (final InputMethodInfo imi : mInputMethodSet) { if (imi.isAuxiliaryIme()) { @@ -118,7 +117,7 @@ final class InputMethodInfoUtils { } private static InputMethodListBuilder getMinimumKeyboardSetWithSystemLocale( - ArrayList<InputMethodInfo> imis, Context context, @Nullable Locale systemLocale, + List<InputMethodInfo> imis, Context context, @Nullable Locale systemLocale, @Nullable Locale fallbackLocale) { // Once the system becomes ready, we pick up at least one keyboard in the following order. // Secondary users fall into this category in general. @@ -167,7 +166,7 @@ final class InputMethodInfoUtils { } static ArrayList<InputMethodInfo> getDefaultEnabledImes( - Context context, ArrayList<InputMethodInfo> imis, boolean onlyMinimum) { + Context context, List<InputMethodInfo> imis, boolean onlyMinimum) { final Locale fallbackLocale = getFallbackLocaleForDefaultIme(imis, context); // We will primarily rely on the system locale, but also keep relying on the fallback locale // as a last resort. @@ -186,7 +185,7 @@ final class InputMethodInfoUtils { } static ArrayList<InputMethodInfo> getDefaultEnabledImes( - Context context, ArrayList<InputMethodInfo> imis) { + Context context, List<InputMethodInfo> imis) { return getDefaultEnabledImes(context, imis, false /* onlyMinimum */); } @@ -204,7 +203,7 @@ final class InputMethodInfoUtils { */ @Nullable static InputMethodInfo chooseSystemVoiceIme( - @NonNull ArrayMap<String, InputMethodInfo> methodMap, + @NonNull InputMethodMap methodMap, @Nullable String systemSpeechRecognizerPackageName, @Nullable String currentDefaultVoiceImeId) { if (TextUtils.isEmpty(systemSpeechRecognizerPackageName)) { @@ -283,7 +282,7 @@ final class InputMethodInfoUtils { } @Nullable - private static Locale getFallbackLocaleForDefaultIme(ArrayList<InputMethodInfo> imis, + private static Locale getFallbackLocaleForDefaultIme(List<InputMethodInfo> imis, Context context) { // At first, find the fallback locale from the IMEs that are declared as "default" in the // current locale. Note that IME developers can declare an IME as "default" only for diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java index 8448fc233ae2..50340d241347 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java @@ -314,10 +314,6 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub @Nullable private VirtualDeviceManagerInternal mVdmInternal = null; - // All known input methods. - final ArrayList<InputMethodInfo> mMethodList = new ArrayList<>(); - private final ArrayMap<String, InputMethodInfo> mMethodMap = new ArrayMap<>(); - // Mapping from deviceId to the device-specific imeId for that device. @GuardedBy("ImfLock.class") private final SparseArray<String> mVirtualDeviceMethodMap = new SparseArray<>(); @@ -330,7 +326,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub private HardwareKeyboardShortcutController mHardwareKeyboardShortcutController; /** - * Tracks how many times {@link #mMethodMap} was updated. + * Tracks how many times {@link #mSettings} was updated. */ @GuardedBy("ImfLock.class") private int mMethodMapUpdateCount = 0; @@ -472,7 +468,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub @GuardedBy("ImfLock.class") @Nullable InputMethodInfo queryInputMethodForCurrentUserLocked(@NonNull String imeId) { - return mMethodMap.get(imeId); + return mSettings.getMethodMap().get(imeId); } /** @@ -1171,7 +1167,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub // sender userId can be a real user ID or USER_ALL. final int senderUserId = pendingResult.getSendingUserId(); if (senderUserId != UserHandle.USER_ALL) { - if (senderUserId != mSettings.getCurrentUserId()) { + if (senderUserId != mSettings.getUserId()) { // A background user is trying to hide the dialog. Ignore. return; } @@ -1249,7 +1245,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub @GuardedBy("ImfLock.class") private boolean isChangingPackagesOfCurrentUserLocked() { final int userId = getChangingUserId(); - final boolean retval = userId == mSettings.getCurrentUserId(); + final boolean retval = userId == mSettings.getUserId(); if (DEBUG) { if (!retval) { Slog.d(TAG, "--- ignore this call back from a background user: " + userId); @@ -1265,10 +1261,11 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub return false; } String curInputMethodId = mSettings.getSelectedInputMethod(); - final int numImes = mMethodList.size(); + final List<InputMethodInfo> methodList = mSettings.getMethodList(); + final int numImes = methodList.size(); if (curInputMethodId != null) { for (int i = 0; i < numImes; i++) { - InputMethodInfo imi = mMethodList.get(i); + InputMethodInfo imi = methodList.get(i); if (imi.getId().equals(curInputMethodId)) { for (String pkg : packages) { if (imi.getPackageName().equals(pkg)) { @@ -1339,7 +1336,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub @Override public void onPackageDataCleared(String packageName, int uid) { boolean changed = false; - for (InputMethodInfo imi : mMethodList) { + for (InputMethodInfo imi : mSettings.getMethodList()) { if (imi.getPackageName().equals(packageName)) { mAdditionalSubtypeMap.remove(imi.getId()); changed = true; @@ -1347,7 +1344,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub } if (changed) { AdditionalSubtypeUtils.save( - mAdditionalSubtypeMap, mMethodMap, mSettings.getCurrentUserId()); + mAdditionalSubtypeMap, mSettings.getMethodMap(), mSettings.getUserId()); mChangedPackages.add(packageName); } } @@ -1405,10 +1402,11 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub InputMethodInfo curIm = null; String curInputMethodId = mSettings.getSelectedInputMethod(); - final int numImes = mMethodList.size(); + final List<InputMethodInfo> methodList = mSettings.getMethodList(); + final int numImes = methodList.size(); if (curInputMethodId != null) { for (int i = 0; i < numImes; i++) { - InputMethodInfo imi = mMethodList.get(i); + InputMethodInfo imi = methodList.get(i); final String imiId = imi.getId(); if (imiId.equals(curInputMethodId)) { curIm = imi; @@ -1426,8 +1424,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub + imi.getComponent()); mAdditionalSubtypeMap.remove(imi.getId()); AdditionalSubtypeUtils.save(mAdditionalSubtypeMap, - mMethodMap, - mSettings.getCurrentUserId()); + mSettings.getMethodMap(), mSettings.getUserId()); } } } @@ -1441,7 +1438,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub if (change == PACKAGE_TEMPORARY_CHANGE || change == PACKAGE_PERMANENT_CHANGE) { final PackageManager userAwarePackageManager = - getPackageManagerForUser(mContext, mSettings.getCurrentUserId()); + getPackageManagerForUser(mContext, mSettings.getUserId()); ServiceInfo si = null; try { si = userAwarePackageManager.getServiceInfo(curIm.getComponent(), @@ -1577,14 +1574,14 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub void onUnlockUser(@UserIdInt int userId) { synchronized (ImfLock.class) { - final int currentUserId = mSettings.getCurrentUserId(); + final int currentUserId = mSettings.getUserId(); if (DEBUG) { Slog.d(TAG, "onUnlockUser: userId=" + userId + " curUserId=" + currentUserId); } if (userId != currentUserId) { return; } - mSettings = new InputMethodSettings(mMethodMap, userId); + mSettings = InputMethodSettings.createEmptyMap(userId); if (mSystemReady) { // We need to rebuild IMEs. buildInputMethodListLocked(false /* resetDefaultEnabledIme */); @@ -1658,14 +1655,15 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub mLastSwitchUserId = userId; // mSettings should be created before buildInputMethodListLocked - mSettings = new InputMethodSettings(mMethodMap, userId); + mSettings = InputMethodSettings.createEmptyMap(userId); AdditionalSubtypeUtils.load(mAdditionalSubtypeMap, userId); mSwitchingController = - InputMethodSubtypeSwitchingController.createInstanceLocked(context, mMethodMap, - userId); + InputMethodSubtypeSwitchingController.createInstanceLocked(context, + mSettings.getMethodMap(), userId); mHardwareKeyboardShortcutController = - new HardwareKeyboardShortcutController(mMethodMap, userId); + new HardwareKeyboardShortcutController(mSettings.getMethodMap(), + mSettings.getUserId()); mMenuController = new InputMethodMenuController(this); mBindingController = bindingControllerForTesting != null @@ -1696,7 +1694,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub @GuardedBy("ImfLock.class") @UserIdInt int getCurrentImeUserIdLocked() { - return mSettings.getCurrentUserId(); + return mSettings.getUserId(); } private final class InkWindowInitializer implements Runnable { @@ -1723,11 +1721,12 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub private void resetDefaultImeLocked(Context context) { // Do not reset the default (current) IME when it is a 3rd-party IME String selectedMethodId = getSelectedMethodIdLocked(); - if (selectedMethodId != null && !mMethodMap.get(selectedMethodId).isSystem()) { + if (selectedMethodId != null + && !mSettings.getMethodMap().get(selectedMethodId).isSystem()) { return; } final List<InputMethodInfo> suitableImes = InputMethodInfoUtils.getDefaultEnabledImes( - context, mSettings.getEnabledInputMethodListLocked()); + context, mSettings.getEnabledInputMethodList()); if (suitableImes.isEmpty()) { Slog.i(TAG, "No default found"); return; @@ -1783,7 +1782,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub IInputMethodClientInvoker clientToBeReset) { if (DEBUG) { Slog.d(TAG, "Switching user stage 1/3. newUserId=" + newUserId - + " currentUserId=" + mSettings.getCurrentUserId()); + + " currentUserId=" + mSettings.getUserId()); } maybeInitImeNavbarConfigLocked(newUserId); @@ -1791,7 +1790,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub // ContentObserver should be registered again when the user is changed mSettingsObserver.registerContentObserverLocked(newUserId); - mSettings = new InputMethodSettings(mMethodMap, newUserId); + mSettings = InputMethodSettings.createEmptyMap(newUserId); // Additional subtypes should be reset when the user is changed AdditionalSubtypeUtils.load(mAdditionalSubtypeMap, newUserId); final String defaultImiId = mSettings.getSelectedInputMethod(); @@ -1822,7 +1821,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub if (initialUserSwitch) { InputMethodUtils.setNonSelectedSystemImesDisabledUntilUsed( getPackageManagerForUser(mContext, newUserId), - mSettings.getEnabledInputMethodListLocked()); + mSettings.getEnabledInputMethodList()); } if (DEBUG) { @@ -1853,7 +1852,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub } if (!mSystemReady) { mSystemReady = true; - final int currentUserId = mSettings.getCurrentUserId(); + final int currentUserId = mSettings.getUserId(); mStatusBarManagerInternal = LocalServices.getService(StatusBarManagerInternal.class); hideStatusBarIconLocked(); @@ -1874,7 +1873,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub // the "mImeDrawsImeNavBarResLazyInitFuture" field. synchronized (ImfLock.class) { mImeDrawsImeNavBarResLazyInitFuture = null; - if (currentUserId != mSettings.getCurrentUserId()) { + if (currentUserId != mSettings.getUserId()) { // This means that the current user is already switched to other user // before the background task is executed. In this scenario the relevant // field should already be initialized. @@ -1899,7 +1898,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub updateFromSettingsLocked(true); InputMethodUtils.setNonSelectedSystemImesDisabledUntilUsed( getPackageManagerForUser(mContext, currentUserId), - mSettings.getEnabledInputMethodListLocked()); + mSettings.getEnabledInputMethodList()); } } } @@ -1946,7 +1945,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub } synchronized (ImfLock.class) { final int[] resolvedUserIds = InputMethodUtils.resolveUserId(userId, - mSettings.getCurrentUserId(), null); + mSettings.getUserId(), null); if (resolvedUserIds.length != 1) { return Collections.emptyList(); } @@ -1969,7 +1968,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub } synchronized (ImfLock.class) { final int[] resolvedUserIds = InputMethodUtils.resolveUserId(userId, - mSettings.getCurrentUserId(), null); + mSettings.getUserId(), null); if (resolvedUserIds.length != 1) { return Collections.emptyList(); } @@ -1996,14 +1995,14 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub } // Check if selected IME of current user supports handwriting. - if (userId == mSettings.getCurrentUserId()) { + if (userId == mSettings.getUserId()) { return mBindingController.supportsStylusHandwriting(); } //TODO(b/197848765): This can be optimized by caching multi-user methodMaps/methodList. //TODO(b/210039666): use cache. - final ArrayMap<String, InputMethodInfo> methodMap = queryMethodMapForUser(userId); - final InputMethodSettings settings = new InputMethodSettings(methodMap, userId); - final InputMethodInfo imi = methodMap.get(settings.getSelectedInputMethod()); + final InputMethodSettings settings = queryMethodMapForUser(userId); + final InputMethodInfo imi = settings.getMethodMap().get( + settings.getSelectedInputMethod()); return imi != null && imi.supportsStylusHandwriting(); } } @@ -2023,23 +2022,19 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub @GuardedBy("ImfLock.class") private List<InputMethodInfo> getInputMethodListLocked(@UserIdInt int userId, @DirectBootAwareness int directBootAwareness, int callingUid) { - final ArrayList<InputMethodInfo> methodList; final InputMethodSettings settings; - if (userId == mSettings.getCurrentUserId() + if (userId == mSettings.getUserId() && directBootAwareness == DirectBootAwareness.AUTO) { - // Create a copy. - methodList = new ArrayList<>(mMethodList); settings = mSettings; } else { - final ArrayMap<String, InputMethodInfo> methodMap = new ArrayMap<>(); - methodList = new ArrayList<>(); final ArrayMap<String, List<InputMethodSubtype>> additionalSubtypeMap = new ArrayMap<>(); AdditionalSubtypeUtils.load(additionalSubtypeMap, userId); - queryInputMethodServicesInternal(mContext, userId, additionalSubtypeMap, methodMap, - methodList, directBootAwareness); - settings = new InputMethodSettings(methodMap, userId); + settings = queryInputMethodServicesInternal(mContext, userId, additionalSubtypeMap, + directBootAwareness); } + // Create a copy. + final ArrayList<InputMethodInfo> methodList = new ArrayList<>(settings.getMethodList()); // filter caller's access to input methods methodList.removeIf(imi -> !canCallerAccessInputMethod(imi.getPackageName(), callingUid, userId, settings)); @@ -2051,13 +2046,12 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub int callingUid) { final ArrayList<InputMethodInfo> methodList; final InputMethodSettings settings; - if (userId == mSettings.getCurrentUserId()) { - methodList = mSettings.getEnabledInputMethodListLocked(); + if (userId == mSettings.getUserId()) { + methodList = mSettings.getEnabledInputMethodList(); settings = mSettings; } else { - final ArrayMap<String, InputMethodInfo> methodMap = queryMethodMapForUser(userId); - settings = new InputMethodSettings(methodMap, userId); - methodList = settings.getEnabledInputMethodListLocked(); + settings = queryMethodMapForUser(userId); + methodList = settings.getEnabledInputMethodList(); } // filter caller's access to input methods methodList.removeIf(imi -> @@ -2116,31 +2110,30 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub @GuardedBy("ImfLock.class") private List<InputMethodSubtype> getEnabledInputMethodSubtypeListLocked(String imiId, boolean allowsImplicitlyEnabledSubtypes, @UserIdInt int userId, int callingUid) { - if (userId == mSettings.getCurrentUserId()) { + if (userId == mSettings.getUserId()) { final InputMethodInfo imi; String selectedMethodId = getSelectedMethodIdLocked(); if (imiId == null && selectedMethodId != null) { - imi = mMethodMap.get(selectedMethodId); + imi = mSettings.getMethodMap().get(selectedMethodId); } else { - imi = mMethodMap.get(imiId); + imi = mSettings.getMethodMap().get(imiId); } if (imi == null || !canCallerAccessInputMethod( imi.getPackageName(), callingUid, userId, mSettings)) { return Collections.emptyList(); } - return mSettings.getEnabledInputMethodSubtypeListLocked( + return mSettings.getEnabledInputMethodSubtypeList( imi, allowsImplicitlyEnabledSubtypes); } - final ArrayMap<String, InputMethodInfo> methodMap = queryMethodMapForUser(userId); - final InputMethodInfo imi = methodMap.get(imiId); + final InputMethodSettings settings = queryMethodMapForUser(userId); + final InputMethodInfo imi = settings.getMethodMap().get(imiId); if (imi == null) { return Collections.emptyList(); } - final InputMethodSettings settings = new InputMethodSettings(methodMap, userId); if (!canCallerAccessInputMethod(imi.getPackageName(), callingUid, userId, settings)) { return Collections.emptyList(); } - return settings.getEnabledInputMethodSubtypeListLocked( + return settings.getEnabledInputMethodSubtypeList( imi, allowsImplicitlyEnabledSubtypes); } @@ -2305,7 +2298,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub final boolean restarting = !initial; final Binder startInputToken = new Binder(); - final StartInputInfo info = new StartInputInfo(mSettings.getCurrentUserId(), + final StartInputInfo info = new StartInputInfo(mSettings.getUserId(), getCurTokenLocked(), mCurTokenDisplayId, getCurIdLocked(), startInputReason, restarting, UserHandle.getUserId(mCurClient.mUid), @@ -2320,9 +2313,9 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub // same-user scenarios. // That said ignoring cross-user scenario will never affect IMEs that do not have // INTERACT_ACROSS_USERS(_FULL) permissions, which is actually almost always the case. - if (mSettings.getCurrentUserId() == UserHandle.getUserId( + if (mSettings.getUserId() == UserHandle.getUserId( mCurClient.mUid)) { - mPackageManagerInternal.grantImplicitAccess(mSettings.getCurrentUserId(), + mPackageManagerInternal.grantImplicitAccess(mSettings.getUserId(), null /* intent */, UserHandle.getAppId(getCurMethodUidLocked()), mCurClient.mUid, true /* direct */); } @@ -2343,7 +2336,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub } String curId = getCurIdLocked(); - final InputMethodInfo curInputMethodInfo = mMethodMap.get(curId); + final InputMethodInfo curInputMethodInfo = mSettings.getMethodMap().get(curId); final boolean suppressesSpellChecker = curInputMethodInfo != null && curInputMethodInfo.suppressesSpellChecker(); final SparseArray<IAccessibilityInputMethodSession> accessibilityInputMethodSessions = @@ -2559,7 +2552,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub mVirtualDeviceMethodMap.get(mDeviceIdToShowIme, currentMethodId); if (Objects.equals(deviceMethodId, currentMethodId)) { return currentMethodId; - } else if (!mMethodMap.containsKey(deviceMethodId)) { + } else if (!mSettings.getMethodMap().containsKey(deviceMethodId)) { if (DEBUG) { Slog.v(TAG, "Disabling IME on virtual device with id " + mDeviceIdToShowIme + " because its custom input method is not available: " + deviceMethodId); @@ -2601,7 +2594,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub if (isSoftInputModeStateVisibleAllowed(unverifiedTargetSdkVersion, startInputFlags)) { return false; } - final InputMethodInfo imi = mMethodMap.get(selectedMethodId); + final InputMethodInfo imi = mSettings.getMethodMap().get(selectedMethodId); if (imi == null) { return false; } @@ -2944,7 +2937,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub } else if (packageName != null) { if (DEBUG) Slog.d(TAG, "show a small icon for the input method"); final PackageManager userAwarePackageManager = - getPackageManagerForUser(mContext, mSettings.getCurrentUserId()); + getPackageManagerForUser(mContext, mSettings.getUserId()); ApplicationInfo applicationInfo = null; try { applicationInfo = userAwarePackageManager.getApplicationInfo(packageName, @@ -3006,7 +2999,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub return false; } if (mWindowManagerInternal.isKeyguardShowingAndNotOccluded() - && mWindowManagerInternal.isKeyguardSecure(mSettings.getCurrentUserId())) { + && mWindowManagerInternal.isKeyguardSecure(mSettings.getUserId())) { return false; } if ((visibility & InputMethodService.IME_ACTIVE) == 0 @@ -3023,7 +3016,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub return false; } - List<InputMethodInfo> imes = mSettings.getEnabledInputMethodListWithFilterLocked( + List<InputMethodInfo> imes = mSettings.getEnabledInputMethodListWithFilter( InputMethodInfo::shouldShowInInputMethodPicker); final int numImes = imes.size(); if (numImes > 2) return true; @@ -3035,7 +3028,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub for (int i = 0; i < numImes; ++i) { final InputMethodInfo imi = imes.get(i); final List<InputMethodSubtype> subtypes = - mSettings.getEnabledInputMethodSubtypeListLocked(imi, true); + mSettings.getEnabledInputMethodSubtypeList(imi, true); final int subtypeCount = subtypes.size(); if (subtypeCount == 0) { ++nonAuxCount; @@ -3185,9 +3178,9 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub void updateInputMethodsFromSettingsLocked(boolean enabledMayChange) { if (enabledMayChange) { final PackageManager userAwarePackageManager = getPackageManagerForUser(mContext, - mSettings.getCurrentUserId()); + mSettings.getUserId()); - List<InputMethodInfo> enabled = mSettings.getEnabledInputMethodListLocked(); + List<InputMethodInfo> enabled = mSettings.getEnabledInputMethodList(); for (int i = 0; i < enabled.size(); i++) { // We allow the user to select "disabled until used" apps, so if they // are enabling one of those here we now need to make it enabled. @@ -3233,18 +3226,18 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub } // TODO: Instantiate mSwitchingController for each user. - if (mSettings.getCurrentUserId() == mSwitchingController.getUserId()) { - mSwitchingController.resetCircularListLocked(mMethodMap); + if (mSettings.getUserId() == mSwitchingController.getUserId()) { + mSwitchingController.resetCircularListLocked(mSettings.getMethodMap()); } else { mSwitchingController = InputMethodSubtypeSwitchingController.createInstanceLocked( - mContext, mMethodMap, mSettings.getCurrentUserId()); + mContext, mSettings.getMethodMap(), mSettings.getUserId()); } // TODO: Instantiate mHardwareKeyboardShortcutController for each user. - if (mSettings.getCurrentUserId() == mHardwareKeyboardShortcutController.getUserId()) { - mHardwareKeyboardShortcutController.reset(mMethodMap); + if (mSettings.getUserId() == mHardwareKeyboardShortcutController.getUserId()) { + mHardwareKeyboardShortcutController.reset(mSettings.getMethodMap()); } else { mHardwareKeyboardShortcutController = new HardwareKeyboardShortcutController( - mMethodMap, mSettings.getCurrentUserId()); + mSettings.getMethodMap(), mSettings.getUserId()); } sendOnNavButtonFlagsChangedLocked(); } @@ -3268,14 +3261,14 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub @GuardedBy("ImfLock.class") void setInputMethodLocked(String id, int subtypeId, int deviceId) { - InputMethodInfo info = mMethodMap.get(id); + InputMethodInfo info = mSettings.getMethodMap().get(id); if (info == null) { throw getExceptionForUnknownImeId(id); } // See if we need to notify a subtype change within the same IME. if (id.equals(getSelectedMethodIdLocked())) { - final int userId = mSettings.getCurrentUserId(); + final int userId = mSettings.getUserId(); final int subtypeCount = info.getSubtypeCount(); if (subtypeCount <= 0) { notifyInputMethodSubtypeChangedLocked(userId, info, null); @@ -3786,7 +3779,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub return InputBindResult.USER_SWITCHING; } final int[] profileIdsWithDisabled = mUserManagerInternal.getProfileIds( - mSettings.getCurrentUserId(), false /* enabledOnly */); + mSettings.getUserId(), false /* enabledOnly */); for (int profileId : profileIdsWithDisabled) { if (profileId == userId) { scheduleSwitchUserTaskLocked(userId, cs.mClient); @@ -3805,7 +3798,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub mVisibilityStateComputer.mShowForced = false; } - final int currentUserId = mSettings.getCurrentUserId(); + final int currentUserId = mSettings.getUserId(); if (userId != currentUserId) { if (ArrayUtils.contains( mUserManagerInternal.getProfileIds(currentUserId, false), userId)) { @@ -3949,7 +3942,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub && mCurFocusedWindowClient.mClient.asBinder() == client.asBinder()) { return true; } - if (mSettings.getCurrentUserId() != UserHandle.getUserId(uid)) { + if (mSettings.getUserId() != UserHandle.getUserId(uid)) { return false; } if (getCurIntentLocked() != null && InputMethodUtils.checkIfPackageBelongsToUid( @@ -4017,7 +4010,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub if (!calledWithValidTokenLocked(token)) { return; } - final InputMethodInfo imi = mMethodMap.get(id); + final InputMethodInfo imi = mSettings.getMethodMap().get(id); if (imi == null || !canCallerAccessInputMethod( imi.getPackageName(), callingUid, userId, mSettings)) { throw getExceptionForUnknownImeId(id); @@ -4035,7 +4028,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub if (!calledWithValidTokenLocked(token)) { return; } - final InputMethodInfo imi = mMethodMap.get(id); + final InputMethodInfo imi = mSettings.getMethodMap().get(id); if (imi == null || !canCallerAccessInputMethod( imi.getPackageName(), callingUid, userId, mSettings)) { throw getExceptionForUnknownImeId(id); @@ -4055,10 +4048,10 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub if (!calledWithValidTokenLocked(token)) { return false; } - final Pair<String, String> lastIme = mSettings.getLastInputMethodAndSubtypeLocked(); + final Pair<String, String> lastIme = mSettings.getLastInputMethodAndSubtype(); final InputMethodInfo lastImi; if (lastIme != null) { - lastImi = mMethodMap.get(lastIme.first); + lastImi = mSettings.getMethodMap().get(lastIme.first); } else { lastImi = null; } @@ -4082,7 +4075,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub // This is a safety net. If the currentSubtype can't be added to the history // and the framework couldn't find the last ime, we will make the last ime be // the most applicable enabled keyboard subtype of the system imes. - final List<InputMethodInfo> enabled = mSettings.getEnabledInputMethodListLocked(); + final List<InputMethodInfo> enabled = mSettings.getEnabledInputMethodList(); if (enabled != null) { final int enabledCount = enabled.size(); final String locale; @@ -4090,14 +4083,13 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub && !TextUtils.isEmpty(mCurrentSubtype.getLocale())) { locale = mCurrentSubtype.getLocale(); } else { - locale = SystemLocaleWrapper.get(mSettings.getCurrentUserId()).get(0) - .toString(); + locale = SystemLocaleWrapper.get(mSettings.getUserId()).get(0).toString(); } for (int i = 0; i < enabledCount; ++i) { final InputMethodInfo imi = enabled.get(i); if (imi.getSubtypeCount() > 0 && imi.isSystem()) { InputMethodSubtype keyboardSubtype = - SubtypeUtils.findLastResortApplicableSubtypeLocked( + SubtypeUtils.findLastResortApplicableSubtype( SubtypeUtils.getSubtypes(imi), SubtypeUtils.SUBTYPE_MODE_KEYBOARD, locale, true); if (keyboardSubtype != null) { @@ -4139,7 +4131,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub @GuardedBy("ImfLock.class") private boolean switchToNextInputMethodLocked(@Nullable IBinder token, boolean onlyCurrentIme) { final ImeSubtypeListItem nextSubtype = mSwitchingController.getNextInputMethodLocked( - onlyCurrentIme, mMethodMap.get(getSelectedMethodIdLocked()), mCurrentSubtype); + onlyCurrentIme, mSettings.getMethodMap().get(getSelectedMethodIdLocked()), + mCurrentSubtype); if (nextSubtype == null) { return false; } @@ -4155,8 +4148,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub return false; } final ImeSubtypeListItem nextSubtype = mSwitchingController.getNextInputMethodLocked( - false /* onlyCurrentIme */, mMethodMap.get(getSelectedMethodIdLocked()), - mCurrentSubtype); + false /* onlyCurrentIme */, + mSettings.getMethodMap().get(getSelectedMethodIdLocked()), mCurrentSubtype); return nextSubtype != null; } } @@ -4168,13 +4161,12 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub Manifest.permission.INTERACT_ACROSS_USERS_FULL, null); } synchronized (ImfLock.class) { - if (mSettings.getCurrentUserId() == userId) { - return mSettings.getLastInputMethodSubtypeLocked(); + if (mSettings.getUserId() == userId) { + return mSettings.getLastInputMethodSubtype(); } - final ArrayMap<String, InputMethodInfo> methodMap = queryMethodMapForUser(userId); - final InputMethodSettings settings = new InputMethodSettings(methodMap, userId); - return settings.getLastInputMethodSubtypeLocked(); + final InputMethodSettings settings = queryMethodMapForUser(userId); + return settings.getLastInputMethodSubtype(); } } @@ -4204,7 +4196,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub return; } - if (mSettings.getCurrentUserId() == userId) { + if (mSettings.getUserId() == userId) { if (!mSettings.setAdditionalInputMethodSubtypes(imiId, toBeAdded, mAdditionalSubtypeMap, mPackageManagerInternal, callingUid)) { return; @@ -4218,14 +4210,11 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub return; } - final ArrayMap<String, InputMethodInfo> methodMap = new ArrayMap<>(); - final ArrayList<InputMethodInfo> methodList = new ArrayList<>(); final ArrayMap<String, List<InputMethodSubtype>> additionalSubtypeMap = new ArrayMap<>(); AdditionalSubtypeUtils.load(additionalSubtypeMap, userId); - queryInputMethodServicesInternal(mContext, userId, additionalSubtypeMap, methodMap, - methodList, DirectBootAwareness.AUTO); - final InputMethodSettings settings = new InputMethodSettings(methodMap, userId); + final InputMethodSettings settings = queryInputMethodServicesInternal(mContext, userId, + additionalSubtypeMap, DirectBootAwareness.AUTO); settings.setAdditionalInputMethodSubtypes(imiId, toBeAdded, additionalSubtypeMap, mPackageManagerInternal, callingUid); } @@ -4251,10 +4240,9 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub final long ident = Binder.clearCallingIdentity(); try { synchronized (ImfLock.class) { - final boolean currentUser = (mSettings.getCurrentUserId() == userId); + final boolean currentUser = (mSettings.getUserId() == userId); final InputMethodSettings settings = currentUser - ? mSettings - : new InputMethodSettings(queryMethodMapForUser(userId), userId); + ? mSettings : queryMethodMapForUser(userId); if (!settings.setEnabledInputMethodSubtypes(imeId, subtypeHashCodes)) { return; } @@ -4623,10 +4611,11 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub } return; } - if (mSettings.getCurrentUserId() != mSwitchingController.getUserId()) { + if (mSettings.getUserId() != mSwitchingController.getUserId()) { return; } - final InputMethodInfo imi = mMethodMap.get(getSelectedMethodIdLocked()); + final InputMethodInfo imi = + mSettings.getMethodMap().get(getSelectedMethodIdLocked()); if (imi != null) { mSwitchingController.onUserActionLocked(imi, mCurrentSubtype); } @@ -4684,8 +4673,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub return; } else { // Called with current IME's token. - if (mMethodMap.get(id) != null - && mSettings.getEnabledInputMethodListWithFilterLocked( + if (mSettings.getMethodMap().get(id) != null + && mSettings.getEnabledInputMethodListWithFilter( (info) -> info.getId().equals(id)).isEmpty()) { throw new IllegalStateException("Requested IME is not enabled: " + id); } @@ -4857,8 +4846,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub } synchronized (ImfLock.class) { final boolean isScreenLocked = mWindowManagerInternal.isKeyguardLocked() - && mWindowManagerInternal.isKeyguardSecure( - mSettings.getCurrentUserId()); + && mWindowManagerInternal.isKeyguardSecure(mSettings.getUserId()); final String lastInputMethodId = mSettings.getSelectedInputMethod(); int lastInputMethodSubtypeId = mSettings.getSelectedInputMethodSubtypeId(lastInputMethodId); @@ -4866,7 +4854,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub final List<ImeSubtypeListItem> imList = InputMethodSubtypeSwitchingController .getSortedInputMethodAndSubtypeList( showAuxSubtypes, isScreenLocked, true /* forImeMenu */, - mContext, mMethodMap, mSettings.getCurrentUserId()); + mContext, mSettings.getMethodMap(), mSettings.getUserId()); mMenuController.showInputMethodMenuLocked(showAuxSubtypes, displayId, lastInputMethodId, lastInputMethodSubtypeId, imList); } @@ -5050,7 +5038,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub @GuardedBy("ImfLock.class") private boolean chooseNewDefaultIMELocked() { final InputMethodInfo imi = InputMethodInfoUtils.getMostApplicableDefaultIME( - mSettings.getEnabledInputMethodListLocked()); + mSettings.getEnabledInputMethodList()); if (imi != null) { if (DEBUG) { Slog.d(TAG, "New default IME was selected: " + imi.getId()); @@ -5062,17 +5050,14 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub return false; } - static void queryInputMethodServicesInternal(Context context, + @NonNull + static InputMethodSettings queryInputMethodServicesInternal(Context context, @UserIdInt int userId, ArrayMap<String, List<InputMethodSubtype>> additionalSubtypeMap, - ArrayMap<String, InputMethodInfo> methodMap, ArrayList<InputMethodInfo> methodList, @DirectBootAwareness int directBootAwareness) { final Context userAwareContext = context.getUserId() == userId ? context : context.createContextAsUser(UserHandle.of(userId), 0 /* flags */); - methodList.clear(); - methodMap.clear(); - final int directBootAwarenessFlags; switch (directBootAwareness) { case DirectBootAwareness.ANY: @@ -5095,24 +5080,23 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub new Intent(InputMethod.SERVICE_INTERFACE), PackageManager.ResolveInfoFlags.of(flags)); - methodList.ensureCapacity(services.size()); - methodMap.ensureCapacity(services.size()); - // Note: This is a temporary solution for Bug 261723412. If there is any better solution, // we should remove this data dependency. final List<String> enabledInputMethodList = InputMethodUtils.getEnabledInputMethodIdsForFiltering(context, userId); - filterInputMethodServices(additionalSubtypeMap, methodMap, methodList, - enabledInputMethodList, userAwareContext, services); + final InputMethodMap methodMap = filterInputMethodServices( + additionalSubtypeMap, enabledInputMethodList, userAwareContext, services); + return InputMethodSettings.create(methodMap, userId); } - static void filterInputMethodServices( + @NonNull + static InputMethodMap filterInputMethodServices( ArrayMap<String, List<InputMethodSubtype>> additionalSubtypeMap, - ArrayMap<String, InputMethodInfo> methodMap, ArrayList<InputMethodInfo> methodList, List<String> enabledInputMethodList, Context userAwareContext, List<ResolveInfo> services) { final ArrayMap<String, Integer> imiPackageCount = new ArrayMap<>(); + final ArrayMap<String, InputMethodInfo> methodMap = new ArrayMap<>(services.size()); for (int i = 0; i < services.size(); ++i) { ResolveInfo ri = services.get(i); @@ -5141,7 +5125,6 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub imiPackageCount.put(packageName, 1 + imiPackageCount.getOrDefault(packageName, 0)); - methodList.add(imi); methodMap.put(imi.getId(), imi); if (DEBUG) { Slog.d(TAG, "Found an input method " + imi); @@ -5153,6 +5136,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub Slog.wtf(TAG, "Unable to load input method " + imeId, e); } } + return InputMethodMap.of(methodMap); } @GuardedBy("ImfLock.class") @@ -5168,8 +5152,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub mMethodMapUpdateCount++; mMyPackageMonitor.clearKnownImePackageNamesLocked(); - queryInputMethodServicesInternal(mContext, mSettings.getCurrentUserId(), - mAdditionalSubtypeMap, mMethodMap, mMethodList, DirectBootAwareness.AUTO); + mSettings = queryInputMethodServicesInternal(mContext, mSettings.getUserId(), + mAdditionalSubtypeMap, DirectBootAwareness.AUTO); // Construct the set of possible IME packages for onPackageChanged() to avoid false // negatives when the package state remains to be the same but only the component state is @@ -5181,7 +5165,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub final List<ResolveInfo> allInputMethodServices = mContext.getPackageManager().queryIntentServicesAsUser( new Intent(InputMethod.SERVICE_INTERFACE), - PackageManager.MATCH_DISABLED_COMPONENTS, mSettings.getCurrentUserId()); + PackageManager.MATCH_DISABLED_COMPONENTS, mSettings.getUserId()); final int numImes = allInputMethodServices.size(); for (int i = 0; i < numImes; ++i) { final ServiceInfo si = allInputMethodServices.get(i).serviceInfo; @@ -5196,11 +5180,11 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub if (!resetDefaultEnabledIme) { boolean enabledImeFound = false; boolean enabledNonAuxImeFound = false; - final List<InputMethodInfo> enabledImes = mSettings.getEnabledInputMethodListLocked(); + final List<InputMethodInfo> enabledImes = mSettings.getEnabledInputMethodList(); final int numImes = enabledImes.size(); for (int i = 0; i < numImes; ++i) { final InputMethodInfo imi = enabledImes.get(i); - if (mMethodList.contains(imi)) { + if (mSettings.getMethodMap().containsKey(imi.getId())) { enabledImeFound = true; if (!imi.isAuxiliaryIme()) { enabledNonAuxImeFound = true; @@ -5224,7 +5208,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub if (resetDefaultEnabledIme || reenableMinimumNonAuxSystemImes) { final ArrayList<InputMethodInfo> defaultEnabledIme = - InputMethodInfoUtils.getDefaultEnabledImes(mContext, mMethodList, + InputMethodInfoUtils.getDefaultEnabledImes(mContext, mSettings.getMethodList(), reenableMinimumNonAuxSystemImes); final int numImes = defaultEnabledIme.size(); for (int i = 0; i < numImes; ++i) { @@ -5238,7 +5222,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub final String defaultImiId = mSettings.getSelectedInputMethod(); if (!TextUtils.isEmpty(defaultImiId)) { - if (!mMethodMap.containsKey(defaultImiId)) { + if (!mSettings.getMethodMap().containsKey(defaultImiId)) { Slog.w(TAG, "Default IME is uninstalled. Choose new default IME."); if (chooseNewDefaultIMELocked()) { updateInputMethodsFromSettingsLocked(true); @@ -5252,26 +5236,26 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub updateDefaultVoiceImeIfNeededLocked(); // TODO: Instantiate mSwitchingController for each user. - if (mSettings.getCurrentUserId() == mSwitchingController.getUserId()) { - mSwitchingController.resetCircularListLocked(mMethodMap); + if (mSettings.getUserId() == mSwitchingController.getUserId()) { + mSwitchingController.resetCircularListLocked(mSettings.getMethodMap()); } else { mSwitchingController = InputMethodSubtypeSwitchingController.createInstanceLocked( - mContext, mMethodMap, mSettings.getCurrentUserId()); + mContext, mSettings.getMethodMap(), mSettings.getUserId()); } // TODO: Instantiate mHardwareKeyboardShortcutController for each user. - if (mSettings.getCurrentUserId() == mHardwareKeyboardShortcutController.getUserId()) { - mHardwareKeyboardShortcutController.reset(mMethodMap); + if (mSettings.getUserId() == mHardwareKeyboardShortcutController.getUserId()) { + mHardwareKeyboardShortcutController.reset(mSettings.getMethodMap()); } else { mHardwareKeyboardShortcutController = new HardwareKeyboardShortcutController( - mMethodMap, mSettings.getCurrentUserId()); + mSettings.getMethodMap(), mSettings.getUserId()); } sendOnNavButtonFlagsChangedLocked(); // Notify InputMethodListListeners of the new installed InputMethods. - final List<InputMethodInfo> inputMethodList = new ArrayList<>(mMethodList); + final List<InputMethodInfo> inputMethodList = mSettings.getMethodList(); mHandler.obtainMessage(MSG_DISPATCH_ON_INPUT_METHOD_LIST_UPDATED, - mSettings.getCurrentUserId(), 0 /* unused */, inputMethodList).sendToTarget(); + mSettings.getUserId(), 0 /* unused */, inputMethodList).sendToTarget(); } @GuardedBy("ImfLock.class") @@ -5290,7 +5274,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub mContext.getString(com.android.internal.R.string.config_systemSpeechRecognizer); final String currentDefaultVoiceImeId = mSettings.getDefaultVoiceInputMethod(); final InputMethodInfo newSystemVoiceIme = InputMethodInfoUtils.chooseSystemVoiceIme( - mMethodMap, systemSpeechRecognizer, currentDefaultVoiceImeId); + mSettings.getMethodMap(), systemSpeechRecognizer, currentDefaultVoiceImeId); if (newSystemVoiceIme == null) { if (DEBUG) { Slog.i(TAG, "Found no valid default Voice IME. If the user is still locked," @@ -5341,9 +5325,9 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub return false; } else { final List<Pair<String, ArrayList<String>>> enabledInputMethodsList = mSettings - .getEnabledInputMethodsAndSubtypeListLocked(); + .getEnabledInputMethodsAndSubtypeList(); StringBuilder builder = new StringBuilder(); - if (mSettings.buildAndPutEnabledInputMethodsStrRemovingIdLocked( + if (mSettings.buildAndPutEnabledInputMethodsStrRemovingId( builder, enabledInputMethodsList, id)) { if (mDeviceIdToShowIme == DEVICE_ID_DEFAULT) { // Disabled input method is currently selected, switch to another one. @@ -5357,7 +5341,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub // new default one but only update the settings. InputMethodInfo newDefaultIme = InputMethodInfoUtils.getMostApplicableDefaultIME( - mSettings.getEnabledInputMethodListLocked()); + mSettings.getEnabledInputMethodList()); mSettings.putSelectedDefaultDeviceInputMethod( newDefaultIme == null ? "" : newDefaultIme.getId()); } @@ -5392,7 +5376,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub mCurrentSubtype = getCurrentInputMethodSubtypeLocked(); } } - notifyInputMethodSubtypeChangedLocked(mSettings.getCurrentUserId(), imi, mCurrentSubtype); + notifyInputMethodSubtypeChangedLocked(mSettings.getUserId(), imi, mCurrentSubtype); if (!setSubtypeOnly) { // Set InputMethod here @@ -5402,11 +5386,11 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub @GuardedBy("ImfLock.class") private void resetSelectedInputMethodAndSubtypeLocked(String newDefaultIme) { - InputMethodInfo imi = mMethodMap.get(newDefaultIme); + InputMethodInfo imi = mSettings.getMethodMap().get(newDefaultIme); int lastSubtypeId = NOT_A_SUBTYPE_ID; // newDefaultIme is empty when there is no candidate for the selected IME. if (imi != null && !TextUtils.isEmpty(newDefaultIme)) { - String subtypeHashCode = mSettings.getLastSubtypeForInputMethodLocked(newDefaultIme); + String subtypeHashCode = mSettings.getLastSubtypeForInputMethod(newDefaultIme); if (subtypeHashCode != null) { try { lastSubtypeId = SubtypeUtils.getSubtypeIdFromHashCode(imi, @@ -5433,12 +5417,11 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub Manifest.permission.INTERACT_ACROSS_USERS_FULL, null); } synchronized (ImfLock.class) { - if (mSettings.getCurrentUserId() == userId) { + if (mSettings.getUserId() == userId) { return getCurrentInputMethodSubtypeLocked(); } - final ArrayMap<String, InputMethodInfo> methodMap = queryMethodMapForUser(userId); - final InputMethodSettings settings = new InputMethodSettings(methodMap, userId); + final InputMethodSettings settings = queryMethodMapForUser(userId); return settings.getCurrentInputMethodSubtypeForNonCurrentUsers(); } } @@ -5460,7 +5443,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub return null; } final boolean subtypeIsSelected = mSettings.isSubtypeSelected(); - final InputMethodInfo imi = mMethodMap.get(selectedMethodId); + final InputMethodInfo imi = mSettings.getMethodMap().get(selectedMethodId); if (imi == null || imi.getSubtypeCount() == 0) { return null; } @@ -5472,19 +5455,19 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub // the most applicable subtype from explicitly or implicitly enabled // subtypes. List<InputMethodSubtype> explicitlyOrImplicitlyEnabledSubtypes = - mSettings.getEnabledInputMethodSubtypeListLocked(imi, true); + mSettings.getEnabledInputMethodSubtypeList(imi, true); // If there is only one explicitly or implicitly enabled subtype, // just returns it. if (explicitlyOrImplicitlyEnabledSubtypes.size() == 1) { mCurrentSubtype = explicitlyOrImplicitlyEnabledSubtypes.get(0); } else if (explicitlyOrImplicitlyEnabledSubtypes.size() > 1) { - final String locale = SystemLocaleWrapper.get(mSettings.getCurrentUserId()) + final String locale = SystemLocaleWrapper.get(mSettings.getUserId()) .get(0).toString(); - mCurrentSubtype = SubtypeUtils.findLastResortApplicableSubtypeLocked( + mCurrentSubtype = SubtypeUtils.findLastResortApplicableSubtype( explicitlyOrImplicitlyEnabledSubtypes, SubtypeUtils.SUBTYPE_MODE_KEYBOARD, locale, true); if (mCurrentSubtype == null) { - mCurrentSubtype = SubtypeUtils.findLastResortApplicableSubtypeLocked( + mCurrentSubtype = SubtypeUtils.findLastResortApplicableSubtype( explicitlyOrImplicitlyEnabledSubtypes, null, locale, true); } } @@ -5501,46 +5484,42 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub */ @GuardedBy("ImfLock.class") private InputMethodInfo queryDefaultInputMethodForUserIdLocked(@UserIdInt int userId) { - if (userId == mSettings.getCurrentUserId()) { - return mMethodMap.get(mSettings.getSelectedInputMethod()); + final InputMethodSettings settings; + if (userId == mSettings.getUserId()) { + settings = mSettings; + } else { + final ArrayMap<String, List<InputMethodSubtype>> additionalSubtypeMap = + new ArrayMap<>(); + AdditionalSubtypeUtils.load(additionalSubtypeMap, userId); + settings = queryInputMethodServicesInternal(mContext, userId, + additionalSubtypeMap, DirectBootAwareness.AUTO); } - - final ArrayMap<String, InputMethodInfo> methodMap = new ArrayMap<>(); - final ArrayList<InputMethodInfo> methodList = new ArrayList<>(); - final ArrayMap<String, List<InputMethodSubtype>> additionalSubtypeMap = new ArrayMap<>(); - AdditionalSubtypeUtils.load(additionalSubtypeMap, userId); - queryInputMethodServicesInternal(mContext, userId, additionalSubtypeMap, methodMap, - methodList, DirectBootAwareness.AUTO); - InputMethodSettings settings = new InputMethodSettings(methodMap, userId); - return methodMap.get(settings.getSelectedInputMethod()); + return settings.getMethodMap().get(settings.getSelectedInputMethod()); } - private ArrayMap<String, InputMethodInfo> queryMethodMapForUser(@UserIdInt int userId) { - final ArrayMap<String, InputMethodInfo> methodMap = new ArrayMap<>(); - final ArrayList<InputMethodInfo> methodList = new ArrayList<>(); + private InputMethodSettings queryMethodMapForUser(@UserIdInt int userId) { final ArrayMap<String, List<InputMethodSubtype>> additionalSubtypeMap = new ArrayMap<>(); AdditionalSubtypeUtils.load(additionalSubtypeMap, userId); - queryInputMethodServicesInternal(mContext, userId, additionalSubtypeMap, - methodMap, methodList, DirectBootAwareness.AUTO); - return methodMap; + return queryInputMethodServicesInternal(mContext, userId, additionalSubtypeMap, + DirectBootAwareness.AUTO); } @GuardedBy("ImfLock.class") private boolean switchToInputMethodLocked(String imeId, @UserIdInt int userId) { - if (userId == mSettings.getCurrentUserId()) { - if (!mMethodMap.containsKey(imeId) - || !mSettings.getEnabledInputMethodListLocked() - .contains(mMethodMap.get(imeId))) { + if (userId == mSettings.getUserId()) { + if (!mSettings.getMethodMap().containsKey(imeId) + || !mSettings.getEnabledInputMethodList() + .contains(mSettings.getMethodMap().get(imeId))) { return false; // IME is not found or not enabled. } setInputMethodLocked(imeId, NOT_A_SUBTYPE_ID); return true; } - final ArrayMap<String, InputMethodInfo> methodMap = queryMethodMapForUser(userId); - final InputMethodSettings settings = new InputMethodSettings(methodMap, userId); - if (!methodMap.containsKey(imeId) - || !settings.getEnabledInputMethodListLocked().contains(methodMap.get(imeId))) { + final InputMethodSettings settings = queryMethodMapForUser(userId); + if (!settings.getMethodMap().containsKey(imeId) + || !settings.getEnabledInputMethodList().contains( + settings.getMethodMap().get(imeId))) { return false; // IME is not found or not enabled. } settings.putSelectedInputMethod(imeId); @@ -5578,7 +5557,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub @GuardedBy("ImfLock.class") private void switchKeyboardLayoutLocked(int direction) { - final InputMethodInfo currentImi = mMethodMap.get(getSelectedMethodIdLocked()); + final InputMethodInfo currentImi = mSettings.getMethodMap().get( + getSelectedMethodIdLocked()); if (currentImi == null) { return; } @@ -5590,7 +5570,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub if (nextSubtypeHandle == null) { return; } - final InputMethodInfo nextImi = mMethodMap.get(nextSubtypeHandle.getImeId()); + final InputMethodInfo nextImi = mSettings.getMethodMap().get(nextSubtypeHandle.getImeId()); if (nextImi == null) { return; } @@ -5669,16 +5649,15 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub @Override public boolean setInputMethodEnabled(String imeId, boolean enabled, @UserIdInt int userId) { synchronized (ImfLock.class) { - if (userId == mSettings.getCurrentUserId()) { - if (!mMethodMap.containsKey(imeId)) { + if (userId == mSettings.getUserId()) { + if (!mSettings.getMethodMap().containsKey(imeId)) { return false; // IME is not found. } setInputMethodEnabledLocked(imeId, enabled); return true; } - final ArrayMap<String, InputMethodInfo> methodMap = queryMethodMapForUser(userId); - final InputMethodSettings settings = new InputMethodSettings(methodMap, userId); - if (!methodMap.containsKey(imeId)) { + final InputMethodSettings settings = queryMethodMapForUser(userId); + if (!settings.getMethodMap().containsKey(imeId)) { return false; // IME is not found. } if (enabled) { @@ -5689,9 +5668,9 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub settings.putEnabledInputMethodsStr(newEnabledImeIdsStr); } } else { - settings.buildAndPutEnabledInputMethodsStrRemovingIdLocked( + settings.buildAndPutEnabledInputMethodsStrRemovingId( new StringBuilder(), - settings.getEnabledInputMethodsAndSubtypeListLocked(), imeId); + settings.getEnabledInputMethodsAndSubtypeList(), imeId); } return true; } @@ -5997,10 +5976,11 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub synchronized (ImfLock.class) { p.println("Current Input Method Manager state:"); - int numImes = mMethodList.size(); + final List<InputMethodInfo> methodList = mSettings.getMethodList(); + int numImes = methodList.size(); p.println(" Input Methods: mMethodMapUpdateCount=" + mMethodMapUpdateCount); for (int i = 0; i < numImes; i++) { - InputMethodInfo info = mMethodList.get(i); + InputMethodInfo info = methodList.get(i); p.println(" InputMethod #" + i + ":"); info.dump(p, " "); } @@ -6047,7 +6027,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub p.println(" mSwitchingController:"); mSwitchingController.dump(p); p.println(" mSettings:"); - mSettings.dumpLocked(p, " "); + mSettings.dump(p, " "); p.println(" mStartInputHistory:"); mStartInputHistory.dump(pw, " "); @@ -6311,7 +6291,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub } synchronized (ImfLock.class) { final int[] userIds = InputMethodUtils.resolveUserId(userIdToBeResolved, - mSettings.getCurrentUserId(), shellCommand.getErrPrintWriter()); + mSettings.getUserId(), shellCommand.getErrPrintWriter()); try (PrintWriter pr = shellCommand.getOutPrintWriter()) { for (int userId : userIds) { final List<InputMethodInfo> methods = all @@ -6356,7 +6336,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub PrintWriter error = shellCommand.getErrPrintWriter()) { synchronized (ImfLock.class) { final int[] userIds = InputMethodUtils.resolveUserId(userIdToBeResolved, - mSettings.getCurrentUserId(), shellCommand.getErrPrintWriter()); + mSettings.getUserId(), shellCommand.getErrPrintWriter()); for (int userId : userIds) { if (!userHasDebugPriv(userId, shellCommand)) { continue; @@ -6415,17 +6395,16 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub PrintWriter error) { boolean failedToEnableUnknownIme = false; boolean previouslyEnabled = false; - if (userId == mSettings.getCurrentUserId()) { - if (enabled && !mMethodMap.containsKey(imeId)) { + if (userId == mSettings.getUserId()) { + if (enabled && !mSettings.getMethodMap().containsKey(imeId)) { failedToEnableUnknownIme = true; } else { previouslyEnabled = setInputMethodEnabledLocked(imeId, enabled); } } else { - final ArrayMap<String, InputMethodInfo> methodMap = queryMethodMapForUser(userId); - final InputMethodSettings settings = new InputMethodSettings(methodMap, userId); + final InputMethodSettings settings = queryMethodMapForUser(userId); if (enabled) { - if (!methodMap.containsKey(imeId)) { + if (!settings.getMethodMap().containsKey(imeId)) { failedToEnableUnknownIme = true; } else { final String enabledImeIdsStr = settings.getEnabledInputMethodsStr(); @@ -6438,9 +6417,9 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub } } else { previouslyEnabled = - settings.buildAndPutEnabledInputMethodsStrRemovingIdLocked( + settings.buildAndPutEnabledInputMethodsStrRemovingId( new StringBuilder(), - settings.getEnabledInputMethodsAndSubtypeListLocked(), imeId); + settings.getEnabledInputMethodsAndSubtypeList(), imeId); } } if (failedToEnableUnknownIme) { @@ -6478,7 +6457,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub PrintWriter error = shellCommand.getErrPrintWriter()) { synchronized (ImfLock.class) { final int[] userIds = InputMethodUtils.resolveUserId(userIdToBeResolved, - mSettings.getCurrentUserId(), shellCommand.getErrPrintWriter()); + mSettings.getUserId(), shellCommand.getErrPrintWriter()); for (int userId : userIds) { if (!userHasDebugPriv(userId, shellCommand)) { continue; @@ -6518,7 +6497,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub synchronized (ImfLock.class) { try (PrintWriter out = shellCommand.getOutPrintWriter()) { final int[] userIds = InputMethodUtils.resolveUserId(userIdToBeResolved, - mSettings.getCurrentUserId(), shellCommand.getErrPrintWriter()); + mSettings.getUserId(), shellCommand.getErrPrintWriter()); for (int userId : userIds) { if (!userHasDebugPriv(userId, shellCommand)) { continue; @@ -6530,16 +6509,16 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub } final String nextIme; final List<InputMethodInfo> nextEnabledImes; - if (userId == mSettings.getCurrentUserId()) { + if (userId == mSettings.getUserId()) { hideCurrentInputLocked(mCurFocusedWindow, null /* statsToken */, 0 /* flags */, null /* resultReceiver */, SoftInputShowHideReason.HIDE_RESET_SHELL_COMMAND); mBindingController.unbindCurrentMethod(); // Enable default IMEs, disable others - var toDisable = mSettings.getEnabledInputMethodListLocked(); + var toDisable = mSettings.getEnabledInputMethodList(); var defaultEnabled = InputMethodInfoUtils.getDefaultEnabledImes( - mContext, mMethodList); + mContext, mSettings.getMethodList()); toDisable.removeAll(defaultEnabled); for (InputMethodInfo info : toDisable) { setInputMethodEnabledLocked(info.getId(), false); @@ -6553,23 +6532,19 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub } updateInputMethodsFromSettingsLocked(true /* enabledMayChange */); InputMethodUtils.setNonSelectedSystemImesDisabledUntilUsed( - getPackageManagerForUser(mContext, mSettings.getCurrentUserId()), - mSettings.getEnabledInputMethodListLocked()); + getPackageManagerForUser(mContext, mSettings.getUserId()), + mSettings.getEnabledInputMethodList()); nextIme = mSettings.getSelectedInputMethod(); - nextEnabledImes = mSettings.getEnabledInputMethodListLocked(); + nextEnabledImes = mSettings.getEnabledInputMethodList(); } else { - final ArrayMap<String, InputMethodInfo> methodMap = new ArrayMap<>(); - final ArrayList<InputMethodInfo> methodList = new ArrayList<>(); final ArrayMap<String, List<InputMethodSubtype>> additionalSubtypeMap = new ArrayMap<>(); AdditionalSubtypeUtils.load(additionalSubtypeMap, userId); - queryInputMethodServicesInternal(mContext, userId, additionalSubtypeMap, - methodMap, methodList, DirectBootAwareness.AUTO); - final InputMethodSettings settings = new InputMethodSettings( - methodMap, userId); + final InputMethodSettings settings = queryInputMethodServicesInternal( + mContext, userId, additionalSubtypeMap, DirectBootAwareness.AUTO); nextEnabledImes = InputMethodInfoUtils.getDefaultEnabledImes(mContext, - methodList); + settings.getMethodList()); nextIme = InputMethodInfoUtils.getMostApplicableDefaultIME( nextEnabledImes).getId(); diff --git a/services/core/java/com/android/server/inputmethod/InputMethodMap.java b/services/core/java/com/android/server/inputmethod/InputMethodMap.java new file mode 100644 index 000000000000..a8e5e2ef4f72 --- /dev/null +++ b/services/core/java/com/android/server/inputmethod/InputMethodMap.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.inputmethod; + +import android.annotation.AnyThread; +import android.annotation.IntRange; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.util.ArrayMap; +import android.view.inputmethod.InputMethodInfo; + +import java.util.List; + +/** + * A map from IME ID to {@link InputMethodInfo}, which is guaranteed to be immutable thus + * thread-safe. + */ +final class InputMethodMap { + private static final ArrayMap<String, InputMethodInfo> EMPTY_MAP = + new ArrayMap<>(); + + private final ArrayMap<String, InputMethodInfo> mMap; + + static InputMethodMap emptyMap() { + return new InputMethodMap(EMPTY_MAP); + } + + static InputMethodMap of(@NonNull ArrayMap<String, InputMethodInfo> map) { + return new InputMethodMap(map); + } + + private InputMethodMap(@NonNull ArrayMap<String, InputMethodInfo> map) { + mMap = map.isEmpty() ? EMPTY_MAP : new ArrayMap<>(map); + } + + @AnyThread + @Nullable + InputMethodInfo get(@Nullable String imeId) { + return mMap.get(imeId); + } + + @AnyThread + @NonNull + List<InputMethodInfo> values() { + return List.copyOf(mMap.values()); + } + + @AnyThread + @Nullable + InputMethodInfo valueAt(int index) { + return mMap.valueAt(index); + } + + @AnyThread + boolean containsKey(@Nullable String imeId) { + return mMap.containsKey(imeId); + } + + @AnyThread + @IntRange(from = 0) + int size() { + return mMap.size(); + } +} diff --git a/services/core/java/com/android/server/inputmethod/InputMethodSettings.java b/services/core/java/com/android/server/inputmethod/InputMethodSettings.java index 4c7d7557de7d..a51002be344f 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodSettings.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodSettings.java @@ -16,6 +16,7 @@ package com.android.server.inputmethod; +import android.annotation.AnyThread; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; @@ -58,23 +59,35 @@ final class InputMethodSettings { private static final char INPUT_METHOD_SUBTYPE_SEPARATOR = InputMethodUtils.INPUT_METHOD_SUBTYPE_SEPARATOR; - private final ArrayMap<String, InputMethodInfo> mMethodMap; + private final InputMethodMap mMethodMap; + private final List<InputMethodInfo> mMethodList; + @UserIdInt - private final int mCurrentUserId; + private final int mUserId; private static void buildEnabledInputMethodsSettingString( StringBuilder builder, Pair<String, ArrayList<String>> ime) { builder.append(ime.first); // Inputmethod and subtypes are saved in the settings as follows: // ime0;subtype0;subtype1:ime1;subtype0:ime2:ime3;subtype0;subtype1 - for (String subtypeId : ime.second) { + for (int i = 0; i < ime.second.size(); ++i) { + final String subtypeId = ime.second.get(i); builder.append(INPUT_METHOD_SUBTYPE_SEPARATOR).append(subtypeId); } } - InputMethodSettings(ArrayMap<String, InputMethodInfo> methodMap, @UserIdInt int userId) { + static InputMethodSettings createEmptyMap(@UserIdInt int userId) { + return new InputMethodSettings(InputMethodMap.emptyMap(), userId); + } + + static InputMethodSettings create(InputMethodMap methodMap, @UserIdInt int userId) { + return new InputMethodSettings(methodMap, userId); + } + + private InputMethodSettings(InputMethodMap methodMap, @UserIdInt int userId) { mMethodMap = methodMap; - mCurrentUserId = userId; + mMethodList = methodMap.values(); + mUserId = userId; String ime = getSelectedInputMethod(); String defaultDeviceIme = getSelectedDefaultDeviceInputMethod(); if (defaultDeviceIme != null && !Objects.equals(ime, defaultDeviceIme)) { @@ -83,57 +96,71 @@ final class InputMethodSettings { } } + @AnyThread + @NonNull + InputMethodMap getMethodMap() { + return mMethodMap; + } + + @AnyThread + @NonNull + List<InputMethodInfo> getMethodList() { + return mMethodList; + } + private void putString(@NonNull String key, @Nullable String str) { - SecureSettingsWrapper.putString(key, str, mCurrentUserId); + SecureSettingsWrapper.putString(key, str, mUserId); } @Nullable private String getString(@NonNull String key, @Nullable String defaultValue) { - return SecureSettingsWrapper.getString(key, defaultValue, mCurrentUserId); + return SecureSettingsWrapper.getString(key, defaultValue, mUserId); } private void putInt(String key, int value) { - SecureSettingsWrapper.putInt(key, value, mCurrentUserId); + SecureSettingsWrapper.putInt(key, value, mUserId); } private int getInt(String key, int defaultValue) { - return SecureSettingsWrapper.getInt(key, defaultValue, mCurrentUserId); + return SecureSettingsWrapper.getInt(key, defaultValue, mUserId); } - ArrayList<InputMethodInfo> getEnabledInputMethodListLocked() { - return getEnabledInputMethodListWithFilterLocked(null /* matchingCondition */); + ArrayList<InputMethodInfo> getEnabledInputMethodList() { + return getEnabledInputMethodListWithFilter(null /* matchingCondition */); } @NonNull - ArrayList<InputMethodInfo> getEnabledInputMethodListWithFilterLocked( + ArrayList<InputMethodInfo> getEnabledInputMethodListWithFilter( @Nullable Predicate<InputMethodInfo> matchingCondition) { - return createEnabledInputMethodListLocked( - getEnabledInputMethodsAndSubtypeListLocked(), matchingCondition); + return createEnabledInputMethodList( + getEnabledInputMethodsAndSubtypeList(), matchingCondition); } - List<InputMethodSubtype> getEnabledInputMethodSubtypeListLocked( + List<InputMethodSubtype> getEnabledInputMethodSubtypeList( InputMethodInfo imi, boolean allowsImplicitlyEnabledSubtypes) { List<InputMethodSubtype> enabledSubtypes = - getEnabledInputMethodSubtypeListLocked(imi); + getEnabledInputMethodSubtypeList(imi); if (allowsImplicitlyEnabledSubtypes && enabledSubtypes.isEmpty()) { - enabledSubtypes = SubtypeUtils.getImplicitlyApplicableSubtypesLocked( - SystemLocaleWrapper.get(mCurrentUserId), imi); + enabledSubtypes = SubtypeUtils.getImplicitlyApplicableSubtypes( + SystemLocaleWrapper.get(mUserId), imi); } return InputMethodSubtype.sort(imi, enabledSubtypes); } - List<InputMethodSubtype> getEnabledInputMethodSubtypeListLocked(InputMethodInfo imi) { + List<InputMethodSubtype> getEnabledInputMethodSubtypeList(InputMethodInfo imi) { List<Pair<String, ArrayList<String>>> imsList = - getEnabledInputMethodsAndSubtypeListLocked(); + getEnabledInputMethodsAndSubtypeList(); ArrayList<InputMethodSubtype> enabledSubtypes = new ArrayList<>(); if (imi != null) { - for (Pair<String, ArrayList<String>> imsPair : imsList) { - InputMethodInfo info = mMethodMap.get(imsPair.first); + for (int i = 0; i < imsList.size(); ++i) { + final Pair<String, ArrayList<String>> imsPair = imsList.get(i); + final InputMethodInfo info = mMethodMap.get(imsPair.first); if (info != null && info.getId().equals(imi.getId())) { final int subtypeCount = info.getSubtypeCount(); - for (int i = 0; i < subtypeCount; ++i) { - InputMethodSubtype ims = info.getSubtypeAt(i); - for (String s : imsPair.second) { + for (int j = 0; j < subtypeCount; ++j) { + final InputMethodSubtype ims = info.getSubtypeAt(j); + for (int k = 0; k < imsPair.second.size(); ++k) { + final String s = imsPair.second.get(k); if (String.valueOf(ims.hashCode()).equals(s)) { enabledSubtypes.add(ims); } @@ -146,7 +173,7 @@ final class InputMethodSettings { return enabledSubtypes; } - List<Pair<String, ArrayList<String>>> getEnabledInputMethodsAndSubtypeListLocked() { + List<Pair<String, ArrayList<String>>> getEnabledInputMethodsAndSubtypeList() { final String enabledInputMethodsStr = getEnabledInputMethodsStr(); final TextUtils.SimpleStringSplitter inputMethodSplitter = new TextUtils.SimpleStringSplitter(INPUT_METHOD_SEPARATOR); @@ -178,12 +205,13 @@ final class InputMethodSettings { * * @return the specified id was removed or not. */ - boolean buildAndPutEnabledInputMethodsStrRemovingIdLocked( + boolean buildAndPutEnabledInputMethodsStrRemovingId( StringBuilder builder, List<Pair<String, ArrayList<String>>> imsList, String id) { boolean isRemoved = false; boolean needsAppendSeparator = false; - for (Pair<String, ArrayList<String>> ims : imsList) { - String curId = ims.first; + for (int i = 0; i < imsList.size(); ++i) { + final Pair<String, ArrayList<String>> ims = imsList.get(i); + final String curId = ims.first; if (curId.equals(id)) { // We are disabling this input method, and it is // currently enabled. Skip it to remove from the @@ -205,12 +233,13 @@ final class InputMethodSettings { return isRemoved; } - private ArrayList<InputMethodInfo> createEnabledInputMethodListLocked( + private ArrayList<InputMethodInfo> createEnabledInputMethodList( List<Pair<String, ArrayList<String>>> imsList, Predicate<InputMethodInfo> matchingCondition) { final ArrayList<InputMethodInfo> res = new ArrayList<>(); - for (Pair<String, ArrayList<String>> ims : imsList) { - InputMethodInfo info = mMethodMap.get(ims.first); + for (int i = 0; i < imsList.size(); ++i) { + final Pair<String, ArrayList<String>> ims = imsList.get(i); + final InputMethodInfo info = mMethodMap.get(ims.first); if (info != null && !info.isVrOnly() && (matchingCondition == null || matchingCondition.test(info))) { res.add(info); @@ -239,15 +268,16 @@ final class InputMethodSettings { private void saveSubtypeHistory( List<Pair<String, String>> savedImes, String newImeId, String newSubtypeId) { - StringBuilder builder = new StringBuilder(); + final StringBuilder builder = new StringBuilder(); boolean isImeAdded = false; if (!TextUtils.isEmpty(newImeId) && !TextUtils.isEmpty(newSubtypeId)) { builder.append(newImeId).append(INPUT_METHOD_SUBTYPE_SEPARATOR).append( newSubtypeId); isImeAdded = true; } - for (Pair<String, String> ime : savedImes) { - String imeId = ime.first; + for (int i = 0; i < savedImes.size(); ++i) { + final Pair<String, String> ime = savedImes.get(i); + final String imeId = ime.first; String subtypeId = ime.second; if (TextUtils.isEmpty(subtypeId)) { subtypeId = NOT_A_SUBTYPE_ID_STR; @@ -265,8 +295,9 @@ final class InputMethodSettings { } private void addSubtypeToHistory(String imeId, String subtypeId) { - List<Pair<String, String>> subtypeHistory = loadInputMethodAndSubtypeHistoryLocked(); - for (Pair<String, String> ime : subtypeHistory) { + final List<Pair<String, String>> subtypeHistory = loadInputMethodAndSubtypeHistory(); + for (int i = 0; i < subtypeHistory.size(); ++i) { + final Pair<String, String> ime = subtypeHistory.get(i); if (ime.first.equals(imeId)) { if (DEBUG) { Slog.v(TAG, "Subtype found in the history: " + imeId + ", " @@ -296,14 +327,14 @@ final class InputMethodSettings { } } - Pair<String, String> getLastInputMethodAndSubtypeLocked() { + Pair<String, String> getLastInputMethodAndSubtype() { // Gets the first one from the history - return getLastSubtypeForInputMethodLockedInternal(null); + return getLastSubtypeForInputMethodInternal(null); } @Nullable - InputMethodSubtype getLastInputMethodSubtypeLocked() { - final Pair<String, String> lastIme = getLastInputMethodAndSubtypeLocked(); + InputMethodSubtype getLastInputMethodSubtype() { + final Pair<String, String> lastIme = getLastInputMethodAndSubtype(); // TODO: Handle the case of the last IME with no subtypes if (lastIme == null || TextUtils.isEmpty(lastIme.first) || TextUtils.isEmpty(lastIme.second)) { @@ -324,8 +355,8 @@ final class InputMethodSettings { } } - String getLastSubtypeForInputMethodLocked(String imeId) { - Pair<String, String> ime = getLastSubtypeForInputMethodLockedInternal(imeId); + String getLastSubtypeForInputMethod(String imeId) { + Pair<String, String> ime = getLastSubtypeForInputMethodInternal(imeId); if (ime != null) { return ime.second; } else { @@ -333,17 +364,18 @@ final class InputMethodSettings { } } - private Pair<String, String> getLastSubtypeForInputMethodLockedInternal(String imeId) { - List<Pair<String, ArrayList<String>>> enabledImes = - getEnabledInputMethodsAndSubtypeListLocked(); - List<Pair<String, String>> subtypeHistory = loadInputMethodAndSubtypeHistoryLocked(); - for (Pair<String, String> imeAndSubtype : subtypeHistory) { + private Pair<String, String> getLastSubtypeForInputMethodInternal(String imeId) { + final List<Pair<String, ArrayList<String>>> enabledImes = + getEnabledInputMethodsAndSubtypeList(); + final List<Pair<String, String>> subtypeHistory = loadInputMethodAndSubtypeHistory(); + for (int i = 0; i < subtypeHistory.size(); ++i) { + final Pair<String, String> imeAndSubtype = subtypeHistory.get(i); final String imeInTheHistory = imeAndSubtype.first; // If imeId is empty, returns the first IME and subtype in the history if (TextUtils.isEmpty(imeId) || imeInTheHistory.equals(imeId)) { final String subtypeInTheHistory = imeAndSubtype.second; final String subtypeHashCode = - getEnabledSubtypeHashCodeForInputMethodAndSubtypeLocked( + getEnabledSubtypeHashCodeForInputMethodAndSubtype( enabledImes, imeInTheHistory, subtypeInTheHistory); if (!TextUtils.isEmpty(subtypeHashCode)) { if (DEBUG) { @@ -360,32 +392,34 @@ final class InputMethodSettings { return null; } - private String getEnabledSubtypeHashCodeForInputMethodAndSubtypeLocked(List<Pair<String, + private String getEnabledSubtypeHashCodeForInputMethodAndSubtype(List<Pair<String, ArrayList<String>>> enabledImes, String imeId, String subtypeHashCode) { - final LocaleList localeList = SystemLocaleWrapper.get(mCurrentUserId); - for (Pair<String, ArrayList<String>> enabledIme : enabledImes) { + final LocaleList localeList = SystemLocaleWrapper.get(mUserId); + for (int i = 0; i < enabledImes.size(); ++i) { + final Pair<String, ArrayList<String>> enabledIme = enabledImes.get(i); if (enabledIme.first.equals(imeId)) { final ArrayList<String> explicitlyEnabledSubtypes = enabledIme.second; final InputMethodInfo imi = mMethodMap.get(imeId); - if (explicitlyEnabledSubtypes.size() == 0) { + if (explicitlyEnabledSubtypes.isEmpty()) { // If there are no explicitly enabled subtypes, applicable subtypes are // enabled implicitly. // If IME is enabled and no subtypes are enabled, applicable subtypes // are enabled implicitly, so needs to treat them to be enabled. if (imi != null && imi.getSubtypeCount() > 0) { List<InputMethodSubtype> implicitlyEnabledSubtypes = - SubtypeUtils.getImplicitlyApplicableSubtypesLocked(localeList, + SubtypeUtils.getImplicitlyApplicableSubtypes(localeList, imi); final int numSubtypes = implicitlyEnabledSubtypes.size(); - for (int i = 0; i < numSubtypes; ++i) { - final InputMethodSubtype st = implicitlyEnabledSubtypes.get(i); + for (int j = 0; j < numSubtypes; ++j) { + final InputMethodSubtype st = implicitlyEnabledSubtypes.get(j); if (String.valueOf(st.hashCode()).equals(subtypeHashCode)) { return subtypeHashCode; } } } } else { - for (String s : explicitlyEnabledSubtypes) { + for (int j = 0; j < explicitlyEnabledSubtypes.size(); ++j) { + final String s = explicitlyEnabledSubtypes.get(j); if (s.equals(subtypeHashCode)) { // If both imeId and subtypeId are enabled, return subtypeId. try { @@ -410,7 +444,7 @@ final class InputMethodSettings { return null; } - private List<Pair<String, String>> loadInputMethodAndSubtypeHistoryLocked() { + private List<Pair<String, String>> loadInputMethodAndSubtypeHistory() { ArrayList<Pair<String, String>> imsList = new ArrayList<>(); final String subtypeHistoryStr = getSubtypeHistoryStr(); if (TextUtils.isEmpty(subtypeHistoryStr)) { @@ -449,16 +483,14 @@ final class InputMethodSettings { void putSelectedInputMethod(String imeId) { if (DEBUG) { - Slog.d(TAG, "putSelectedInputMethodStr: " + imeId + ", " - + mCurrentUserId); + Slog.d(TAG, "putSelectedInputMethodStr: " + imeId + ", " + mUserId); } putString(Settings.Secure.DEFAULT_INPUT_METHOD, imeId); } void putSelectedSubtype(int subtypeId) { if (DEBUG) { - Slog.d(TAG, "putSelectedInputMethodSubtypeStr: " + subtypeId + ", " - + mCurrentUserId); + Slog.d(TAG, "putSelectedInputMethodSubtypeStr: " + subtypeId + ", " + mUserId); } putInt(Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE, subtypeId); } @@ -476,24 +508,21 @@ final class InputMethodSettings { String getSelectedDefaultDeviceInputMethod() { final String imi = getString(Settings.Secure.DEFAULT_DEVICE_INPUT_METHOD, null); if (DEBUG) { - Slog.d(TAG, "getSelectedDefaultDeviceInputMethodStr: " + imi + ", " - + mCurrentUserId); + Slog.d(TAG, "getSelectedDefaultDeviceInputMethodStr: " + imi + ", " + mUserId); } return imi; } void putSelectedDefaultDeviceInputMethod(String imeId) { if (DEBUG) { - Slog.d(TAG, "putSelectedDefaultDeviceInputMethodStr: " + imeId + ", " - + mCurrentUserId); + Slog.d(TAG, "putSelectedDefaultDeviceInputMethodStr: " + imeId + ", " + mUserId); } putString(Settings.Secure.DEFAULT_DEVICE_INPUT_METHOD, imeId); } void putDefaultVoiceInputMethod(String imeId) { if (DEBUG) { - Slog.d(TAG, - "putDefaultVoiceInputMethodStr: " + imeId + ", " + mCurrentUserId); + Slog.d(TAG, "putDefaultVoiceInputMethodStr: " + imeId + ", " + mUserId); } putString(Settings.Secure.DEFAULT_VOICE_INPUT_METHOD, imeId); } @@ -517,8 +546,8 @@ final class InputMethodSettings { } @UserIdInt - public int getCurrentUserId() { - return mCurrentUserId; + public int getUserId() { + return mUserId; } int getSelectedInputMethodSubtypeId(String selectedImiId) { @@ -573,7 +602,7 @@ final class InputMethodSettings { // If there are no selected subtypes, the framework will try to find the most applicable // subtype from explicitly or implicitly enabled subtypes. final List<InputMethodSubtype> explicitlyOrImplicitlyEnabledSubtypes = - getEnabledInputMethodSubtypeListLocked(imi, true); + getEnabledInputMethodSubtypeList(imi, true); // If there is only one explicitly or implicitly enabled subtype, just returns it. if (explicitlyOrImplicitlyEnabledSubtypes.isEmpty()) { return null; @@ -581,14 +610,14 @@ final class InputMethodSettings { if (explicitlyOrImplicitlyEnabledSubtypes.size() == 1) { return explicitlyOrImplicitlyEnabledSubtypes.get(0); } - final String locale = SystemLocaleWrapper.get(mCurrentUserId).get(0).toString(); - final InputMethodSubtype subtype = SubtypeUtils.findLastResortApplicableSubtypeLocked( + final String locale = SystemLocaleWrapper.get(mUserId).get(0).toString(); + final InputMethodSubtype subtype = SubtypeUtils.findLastResortApplicableSubtype( explicitlyOrImplicitlyEnabledSubtypes, SubtypeUtils.SUBTYPE_MODE_KEYBOARD, locale, true); if (subtype != null) { return subtype; } - return SubtypeUtils.findLastResortApplicableSubtypeLocked( + return SubtypeUtils.findLastResortApplicableSubtype( explicitlyOrImplicitlyEnabledSubtypes, null, locale, true); } @@ -610,7 +639,7 @@ final class InputMethodSettings { } else { additionalSubtypeMap.put(imi.getId(), subtypes); } - AdditionalSubtypeUtils.save(additionalSubtypeMap, mMethodMap, getCurrentUserId()); + AdditionalSubtypeUtils.save(additionalSubtypeMap, mMethodMap, getUserId()); return true; } @@ -680,7 +709,7 @@ final class InputMethodSettings { return sb.toString(); } - void dumpLocked(final Printer pw, final String prefix) { - pw.println(prefix + "mCurrentUserId=" + mCurrentUserId); + void dump(final Printer pw, final String prefix) { + pw.println(prefix + "mUserId=" + mUserId); } } diff --git a/services/core/java/com/android/server/inputmethod/InputMethodSubtypeSwitchingController.java b/services/core/java/com/android/server/inputmethod/InputMethodSubtypeSwitchingController.java index 834ba20b84fd..1379d166e805 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodSubtypeSwitchingController.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodSubtypeSwitchingController.java @@ -23,7 +23,6 @@ import android.annotation.UserIdInt; import android.content.Context; import android.os.UserHandle; import android.text.TextUtils; -import android.util.ArrayMap; import android.util.ArraySet; import android.util.Printer; import android.util.Slog; @@ -158,15 +157,15 @@ final class InputMethodSubtypeSwitchingController { static List<ImeSubtypeListItem> getSortedInputMethodAndSubtypeList( boolean includeAuxiliarySubtypes, boolean isScreenLocked, boolean forImeMenu, - @NonNull Context context, @NonNull ArrayMap<String, InputMethodInfo> methodMap, + @NonNull Context context, @NonNull InputMethodMap methodMap, @UserIdInt int userId) { final Context userAwareContext = context.getUserId() == userId ? context : context.createContextAsUser(UserHandle.of(userId), 0 /* flags */); final String mSystemLocaleStr = SystemLocaleWrapper.get(userId).get(0).toLanguageTag(); - final InputMethodSettings settings = new InputMethodSettings(methodMap, userId); + final InputMethodSettings settings = InputMethodSettings.create(methodMap, userId); - final ArrayList<InputMethodInfo> imis = settings.getEnabledInputMethodListLocked(); + final ArrayList<InputMethodInfo> imis = settings.getEnabledInputMethodList(); if (imis.isEmpty()) { return new ArrayList<>(); } @@ -184,7 +183,7 @@ final class InputMethodSubtypeSwitchingController { continue; } final List<InputMethodSubtype> explicitlyOrImplicitlyEnabledSubtypeList = - settings.getEnabledInputMethodSubtypeListLocked(imi, true); + settings.getEnabledInputMethodSubtypeList(imi, true); final ArraySet<String> enabledSubtypeSet = new ArraySet<>(); for (InputMethodSubtype subtype : explicitlyOrImplicitlyEnabledSubtypeList) { enabledSubtypeSet.add(String.valueOf(subtype.hashCode())); @@ -479,7 +478,7 @@ final class InputMethodSubtypeSwitchingController { private ControllerImpl mController; private InputMethodSubtypeSwitchingController(@NonNull Context context, - @NonNull ArrayMap<String, InputMethodInfo> methodMap, @UserIdInt int userId) { + @NonNull InputMethodMap methodMap, @UserIdInt int userId) { mContext = context; mUserId = userId; mController = ControllerImpl.createFrom(null, @@ -491,7 +490,7 @@ final class InputMethodSubtypeSwitchingController { @NonNull public static InputMethodSubtypeSwitchingController createInstanceLocked( @NonNull Context context, - @NonNull ArrayMap<String, InputMethodInfo> methodMap, @UserIdInt int userId) { + @NonNull InputMethodMap methodMap, @UserIdInt int userId) { return new InputMethodSubtypeSwitchingController(context, methodMap, userId); } @@ -511,8 +510,7 @@ final class InputMethodSubtypeSwitchingController { mController.onUserActionLocked(imi, subtype); } - public void resetCircularListLocked( - @NonNull ArrayMap<String, InputMethodInfo> methodMap) { + public void resetCircularListLocked(@NonNull InputMethodMap methodMap) { mController = ControllerImpl.createFrom(mController, getSortedInputMethodAndSubtypeList( false /* includeAuxiliarySubtypes */, false /* isScreenLocked */, diff --git a/services/core/java/com/android/server/inputmethod/LocaleUtils.java b/services/core/java/com/android/server/inputmethod/LocaleUtils.java index 7d090dbcc5d8..0b16af29da28 100644 --- a/services/core/java/com/android/server/inputmethod/LocaleUtils.java +++ b/services/core/java/com/android/server/inputmethod/LocaleUtils.java @@ -212,10 +212,16 @@ final class LocaleUtils { /** * Returns the language component of a given locale string. - * TODO: Use {@link Locale#toLanguageTag()} and {@link Locale#forLanguageTag(String)} + * TODO(b/321064051): Switch to {@link + * com.android.internal.inputmethod.SubtypeLocaleUtils#constructLocaleFromString(String)} */ static String getLanguageFromLocaleString(String locale) { - return Locale.forLanguageTag(locale).getLanguage(); + final int idx = locale.indexOf('_'); + if (idx < 0) { + return locale; + } else { + return locale.substring(0, idx); + } } static Locale getSystemLocaleFromContext(Context context) { diff --git a/services/core/java/com/android/server/inputmethod/SubtypeUtils.java b/services/core/java/com/android/server/inputmethod/SubtypeUtils.java index 95df99855dcf..3d5c867768ac 100644 --- a/services/core/java/com/android/server/inputmethod/SubtypeUtils.java +++ b/services/core/java/com/android/server/inputmethod/SubtypeUtils.java @@ -26,7 +26,6 @@ import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodSubtype; import com.android.internal.annotations.GuardedBy; -import com.android.internal.annotations.VisibleForTesting; import java.util.ArrayList; import java.util.List; @@ -52,7 +51,7 @@ final class SubtypeUtils { "EnabledWhenDefaultIsNotAsciiCapable"; // A temporary workaround for the performance concerns in - // #getImplicitlyApplicableSubtypesLocked(Resources, InputMethodInfo). + // #getImplicitlyApplicableSubtypes(Resources, InputMethodInfo). // TODO: Optimize all the critical paths including this one. // TODO(b/235661780): Make the cache supports multi-users. private static final Object sCacheLock = new Object(); @@ -121,9 +120,8 @@ final class SubtypeUtils { private static final LocaleUtils.LocaleExtractor<InputMethodSubtype> sSubtypeToLocale = source -> source != null ? source.getLocaleObject() : null; - @VisibleForTesting @NonNull - static ArrayList<InputMethodSubtype> getImplicitlyApplicableSubtypesLocked( + static ArrayList<InputMethodSubtype> getImplicitlyApplicableSubtypes( @NonNull LocaleList systemLocales, InputMethodInfo imi) { synchronized (sCacheLock) { // We intentionally do not use InputMethodInfo#equals(InputMethodInfo) here because @@ -133,11 +131,11 @@ final class SubtypeUtils { } } - // Note: Only resource info in "res" is used in getImplicitlyApplicableSubtypesLockedImpl(). - // TODO: Refactor getImplicitlyApplicableSubtypesLockedImpl() so that it can receive + // Note: Only resource info in "res" is used in getImplicitlyApplicableSubtypesImpl(). + // TODO: Refactor getImplicitlyApplicableSubtypesImpl() so that it can receive // LocaleList rather than Resource. final ArrayList<InputMethodSubtype> result = - getImplicitlyApplicableSubtypesLockedImpl(systemLocales, imi); + getImplicitlyApplicableSubtypesImpl(systemLocales, imi); synchronized (sCacheLock) { // Both LocaleList and InputMethodInfo are immutable. No need to copy them here. sCachedSystemLocales = systemLocales; @@ -147,7 +145,7 @@ final class SubtypeUtils { return result; } - private static ArrayList<InputMethodSubtype> getImplicitlyApplicableSubtypesLockedImpl( + private static ArrayList<InputMethodSubtype> getImplicitlyApplicableSubtypesImpl( @NonNull LocaleList systemLocales, InputMethodInfo imi) { final List<InputMethodSubtype> subtypes = getSubtypes(imi); final String systemLocale = systemLocales.get(0).toString(); @@ -215,7 +213,7 @@ final class SubtypeUtils { } if (applicableSubtypes.isEmpty()) { - InputMethodSubtype lastResortKeyboardSubtype = findLastResortApplicableSubtypeLocked( + InputMethodSubtype lastResortKeyboardSubtype = findLastResortApplicableSubtype( subtypes, SUBTYPE_MODE_KEYBOARD, systemLocale, true); if (lastResortKeyboardSubtype != null) { applicableSubtypes.add(lastResortKeyboardSubtype); @@ -244,7 +242,7 @@ final class SubtypeUtils { * * @return the most applicable subtypeId */ - static InputMethodSubtype findLastResortApplicableSubtypeLocked( + static InputMethodSubtype findLastResortApplicableSubtype( List<InputMethodSubtype> subtypes, String mode, @NonNull String locale, boolean canIgnoreLocaleAsLastResort) { if (subtypes == null || subtypes.isEmpty()) { diff --git a/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java b/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java index 9c4225dc2542..39df5be0f2fa 100644 --- a/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java +++ b/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java @@ -1384,7 +1384,8 @@ public class GnssLocationProvider extends AbstractLocationProvider implements try { reportLocation(LocationResult.wrap(location).validate()); } catch (BadLocationException e) { - throw new IllegalArgumentException(e); + Log.e(TAG, "Dropping invalid location: " + e); + return; } if (mStarted) { @@ -1759,7 +1760,8 @@ public class GnssLocationProvider extends AbstractLocationProvider implements try { reportLocation(LocationResult.wrap(locations).validate()); } catch (BadLocationException e) { - throw new IllegalArgumentException(e); + Log.e(TAG, "Dropping invalid locations: " + e); + return; } } diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java index 28a1c7ad0540..85a131579497 100644 --- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java +++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java @@ -2336,6 +2336,11 @@ class MediaRouter2ServiceImpl { mSystemProvider.getDefaultRoute()); } + private static String getPackageNameFromNullableRecord( + @Nullable RouterRecord routerRecord) { + return routerRecord != null ? routerRecord.mPackageName : "<null router record>"; + } + private static String toLoggingMessage( String source, String providerId, ArrayList<MediaRoute2Info> routes) { String routesString = @@ -2573,8 +2578,17 @@ class MediaRouter2ServiceImpl { RouterRecord matchingRecord = mSessionToRouterMap.get(uniqueSessionId); if (matchingRecord != routerRecord) { - Slog.w(TAG, "Ignoring " + description + " route from non-matching router. " - + "packageName=" + routerRecord.mPackageName + " route=" + route); + Slog.w( + TAG, + "Ignoring " + + description + + " route from non-matching router." + + " routerRecordPackageName=" + + getPackageNameFromNullableRecord(routerRecord) + + " matchingRecordPackageName=" + + getPackageNameFromNullableRecord(matchingRecord) + + " route=" + + route); return false; } @@ -2613,9 +2627,15 @@ class MediaRouter2ServiceImpl { @Nullable RouterRecord routerRecord, @NonNull String uniqueSessionId) { final RouterRecord matchingRecord = mSessionToRouterMap.get(uniqueSessionId); if (matchingRecord != routerRecord) { - Slog.w(TAG, "Ignoring releasing session from non-matching router. packageName=" - + (routerRecord == null ? null : routerRecord.mPackageName) - + " uniqueSessionId=" + uniqueSessionId); + Slog.w( + TAG, + "Ignoring releasing session from non-matching router." + + " routerRecordPackageName=" + + getPackageNameFromNullableRecord(routerRecord) + + " matchingRecordPackageName=" + + getPackageNameFromNullableRecord(matchingRecord) + + " uniqueSessionId=" + + uniqueSessionId); return; } diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 308d441fb871..425659e38492 100755 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -282,6 +282,7 @@ import android.service.notification.NotificationStats; import android.service.notification.StatusBarNotification; import android.service.notification.ZenModeConfig; import android.service.notification.ZenModeProto; +import android.service.notification.ZenPolicy; import android.telecom.TelecomManager; import android.telephony.PhoneStateListener; import android.telephony.TelephonyManager; @@ -5968,6 +5969,20 @@ public class NotificationManagerService extends SystemService { } } + /** + * Gets the device-default zen policy as a ZenPolicy. + */ + @Override + public ZenPolicy getDefaultZenPolicy() { + enforceSystemOrSystemUI("INotificationManager.getDefaultZenPolicy"); + final long identity = Binder.clearCallingIdentity(); + try { + return mZenModeHelper.getDefaultZenPolicy(); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + @Override public List<String> getEnabledNotificationListenerPackages() { checkCallerIsSystem(); diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java index 153af13b61b4..c067fa068b12 100644 --- a/services/core/java/com/android/server/notification/ZenModeHelper.java +++ b/services/core/java/com/android/server/notification/ZenModeHelper.java @@ -604,6 +604,14 @@ public class ZenModeHelper { ZenRule rule = newConfig.automaticRules.get(implicitRuleId(callingPkg)); if (rule == null) { rule = newImplicitZenRule(callingPkg); + + // For new implicit rules, create a policy matching the current global + // (manual rule) settings, for consistency with the policy that + // would apply if changing the global interruption filter. We only do this + // for newly created rules, as existing rules have a pre-existing policy + // (whether initialized here or set via app or user). + rule.zenPolicy = mConfig.toZenPolicy(); + newConfig.automaticRules.put(rule.id, rule); } // If the user has changed the rule's *zenMode*, then don't let app overwrite it. @@ -615,6 +623,7 @@ public class ZenModeHelper { rule.condition = new Condition(rule.conditionId, mContext.getString(R.string.zen_mode_implicit_activated), Condition.STATE_TRUE); + setConfigLocked(newConfig, /* triggeringComponent= */ null, UPDATE_ORIGIN_APP, "applyGlobalZenModeAsImplicitZenRule", callingUid); } @@ -643,8 +652,10 @@ public class ZenModeHelper { return; } ZenModeConfig newConfig = mConfig.copy(); + boolean isNew = false; ZenRule rule = newConfig.automaticRules.get(implicitRuleId(callingPkg)); if (rule == null) { + isNew = true; rule = newImplicitZenRule(callingPkg); rule.zenMode = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS; newConfig.automaticRules.put(rule.id, rule); @@ -652,10 +663,20 @@ public class ZenModeHelper { // If the user has changed the rule's *ZenPolicy*, then don't let app overwrite it. // We allow the update if the user has only changed other aspects of the rule. if (rule.zenPolicyUserModifiedFields == 0) { + ZenPolicy newZenPolicy = ZenAdapters.notificationPolicyToZenPolicy(policy); + if (isNew) { + // For new rules only, fill anything underspecified in the new policy with + // values from the global configuration, for consistency with the policy that + // would take effect if changing the global policy. + // Note that NotificationManager.Policy cannot have any unset priority + // categories, but *can* have unset visual effects, which is why we do this. + newZenPolicy = mConfig.toZenPolicy().overwrittenWith(newZenPolicy); + } updatePolicy( rule, - ZenAdapters.notificationPolicyToZenPolicy(policy), - /* updateBitmask= */ false); + newZenPolicy, + /* updateBitmask= */ false, + isNew); setConfigLocked(newConfig, /* triggeringComponent= */ null, UPDATE_ORIGIN_APP, "applyGlobalPolicyAsImplicitZenRule", callingUid); @@ -685,6 +706,11 @@ public class ZenModeHelper { } ZenRule implicitRule = mConfig.automaticRules.get(implicitRuleId(callingPkg)); if (implicitRule != null && implicitRule.zenPolicy != null) { + // toNotificationPolicy takes defaults from mConfig, and technically, those are not + // the defaults that would apply if any fields were unset. However, all rules should + // have all fields set in their ZenPolicy objects upon rule creation, so in + // practice, this is only filling in the areChannelsBypassingDnd field, which is a + // state rather than a part of the policy. return mConfig.toNotificationPolicy(implicitRule.zenPolicy); } else { return getNotificationPolicy(); @@ -1072,7 +1098,8 @@ public class ZenModeHelper { rule.zenMode = newZenMode; // Updates the bitmask and values for all policy fields, based on the origin. - updatePolicy(rule, automaticZenRule.getZenPolicy(), updateBitmask); + updatePolicy(rule, automaticZenRule.getZenPolicy(), updateBitmask, isNew); + // Updates the bitmask and values for all device effect fields, based on the origin. updateZenDeviceEffects(rule, automaticZenRule.getDeviceEffects(), origin == UPDATE_ORIGIN_APP, updateBitmask); @@ -1111,14 +1138,19 @@ public class ZenModeHelper { /** * Modifies the {@link ZenPolicy} associated to a new or updated ZenRule. * - * <p>The new policy is {@code newPolicy}, while the user-modified bitmask is updated to reflect - * the changes being applied (if applicable, i.e. if the update is from the user). + * <p>The update takes any set fields in {@code newPolicy} as new policy settings for the + * provided {@code ZenRule}, keeping any pre-existing settings from {@code zenRule.zenPolicy} + * for any unset policy fields in {@code newPolicy}. The user-modified bitmask is updated to + * reflect the changes being applied (if applicable, i.e. if the update is from the user). */ private void updatePolicy(ZenRule zenRule, @Nullable ZenPolicy newPolicy, - boolean updateBitmask) { + boolean updateBitmask, boolean isNew) { if (newPolicy == null) { - // TODO: b/319242206 - Treat as newPolicy == default policy and continue below. - zenRule.zenPolicy = null; + if (isNew) { + // Newly created rule with no provided policy; fill in with the default. + zenRule.zenPolicy = mDefaultConfig.toZenPolicy(); + } + // Otherwise, a null policy means no policy changes, so we can stop here. return; } @@ -1127,6 +1159,16 @@ public class ZenModeHelper { ZenPolicy oldPolicy = zenRule.zenPolicy != null ? zenRule.zenPolicy : mDefaultConfig.toZenPolicy(); + // If this is updating a rule rather than creating a new one, keep any fields from the + // old policy if they are unspecified in the new policy. For newly created rules, oldPolicy + // has been set to the default settings above, so any unspecified fields in a newly created + // policy are filled with default values. Then use the fully-specified version of the new + // policy for comparison below. + // + // Although we do not expect a policy update from the user to contain any unset fields, + // filling in fields here also guards against any unset fields counting as a "diff" when + // comparing fields for bitmask editing below. + newPolicy = oldPolicy.overwrittenWith(newPolicy); zenRule.zenPolicy = newPolicy; if (updateBitmask) { @@ -1452,11 +1494,27 @@ public class ZenModeHelper { } allRulesDisabled &= !automaticRule.enabled; + + // Upon upgrading to a version with modes_api enabled, keep all behaviors of + // rules with null ZenPolicies explicitly as a copy of the global policy. + if (Flags.modesApi() && config.version < ZenModeConfig.XML_VERSION_MODES_API) { + // Keep the manual ("global") policy that from config. + ZenPolicy manualRulePolicy = config.toZenPolicy(); + if (automaticRule.zenPolicy == null) { + automaticRule.zenPolicy = manualRulePolicy; + } else { + // newPolicy is a policy with all unset fields in the rule's zenPolicy + // set to their values from the values in config. Then convert that back + // to ZenPolicy to store with the automatic zen rule. + automaticRule.zenPolicy = + manualRulePolicy.overwrittenWith(automaticRule.zenPolicy); + } + } } } if (!hasDefaultRules && allRulesDisabled - && (forRestore || config.version < ZenModeConfig.XML_VERSION)) { + && (forRestore || config.version < ZenModeConfig.XML_VERSION_ZEN_UPGRADE)) { // reset zen automatic rules to default on restore or upgrade if: // - doesn't already have default rules and // - all previous automatic rules were disabled @@ -1473,7 +1531,7 @@ public class ZenModeHelper { // Resolve user id for settings. userId = userId == UserHandle.USER_ALL ? UserHandle.USER_SYSTEM : userId; - if (config.version < ZenModeConfig.XML_VERSION) { + if (config.version < ZenModeConfig.XML_VERSION_ZEN_UPGRADE) { Settings.Secure.putIntForUser(mContext.getContentResolver(), Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 1, userId); } else { @@ -1600,6 +1658,14 @@ public class ZenModeHelper { return mConsolidatedPolicy.copy(); } + /** + * Returns a copy of the device default policy as a ZenPolicy object. + */ + @VisibleForTesting + protected ZenPolicy getDefaultZenPolicy() { + return mDefaultConfig.toZenPolicy(); + } + @GuardedBy("mConfigLock") private boolean setConfigLocked(ZenModeConfig config, ComponentName triggeringComponent, @ConfigChangeOrigin int origin, String reason, int callingUid) { @@ -1783,7 +1849,7 @@ public class ZenModeHelper { } @GuardedBy("mConfigLock") - private void applyCustomPolicy(ZenPolicy policy, ZenRule rule) { + private void applyCustomPolicy(ZenPolicy policy, ZenRule rule, boolean useManualConfig) { if (rule.zenMode == Global.ZEN_MODE_NO_INTERRUPTIONS) { policy.apply(new ZenPolicy.Builder() .disallowAllSounds() @@ -1797,8 +1863,22 @@ public class ZenModeHelper { } else if (rule.zenPolicy != null) { policy.apply(rule.zenPolicy); } else { - // active rule with no specified policy inherits the default settings - policy.apply(mConfig.toZenPolicy()); + if (Flags.modesApi()) { + if (useManualConfig) { + // manual rule is configured using the settings stored directly in mConfig + policy.apply(mConfig.toZenPolicy()); + } else { + // under modes_api flag, an active automatic rule with no specified policy + // inherits the device default settings as stored in mDefaultConfig. While the + // rule's policy fields should be set upon creation, this is a fallback to + // catch any that may have fallen through the cracks. + Log.wtf(TAG, "active automatic rule found with no specified policy: " + rule); + policy.apply(mDefaultConfig.toZenPolicy()); + } + } else { + // active rule with no specified policy inherits the global config settings + policy.apply(mConfig.toZenPolicy()); + } } } @@ -1810,7 +1890,7 @@ public class ZenModeHelper { ZenPolicy policy = new ZenPolicy(); ZenDeviceEffects.Builder deviceEffectsBuilder = new ZenDeviceEffects.Builder(); if (mConfig.manualRule != null) { - applyCustomPolicy(policy, mConfig.manualRule); + applyCustomPolicy(policy, mConfig.manualRule, true); if (Flags.modesApi()) { deviceEffectsBuilder.add(mConfig.manualRule.zenDeviceEffects); } @@ -1822,7 +1902,7 @@ public class ZenModeHelper { // policy. This is relevant in case some other active rule has a more // restrictive INTERRUPTION_FILTER but a more lenient ZenPolicy! if (!Flags.modesApi() || automaticRule.zenMode != Global.ZEN_MODE_OFF) { - applyCustomPolicy(policy, automaticRule); + applyCustomPolicy(policy, automaticRule, false); } if (Flags.modesApi()) { deviceEffectsBuilder.add(automaticRule.zenDeviceEffects); @@ -1830,6 +1910,14 @@ public class ZenModeHelper { } } + // While mConfig.toNotificationPolicy fills in any unset fields from the provided + // config (which, in this case is the manual "global" config), under modes API changes, + // we should have no remaining unset fields: the manual policy gets every field from + // the global policy, and each automatic rule has all policy fields filled in on + // creation or update. + // However, the piece of information that comes from mConfig that we must keep is the + // areChannelsBypassingDnd bit, which is a state, rather than a policy, and even when + // all policy fields are set, this state comes to the new policy from this call. Policy newPolicy = mConfig.toNotificationPolicy(policy); if (!Objects.equals(mConsolidatedPolicy, newPolicy)) { mConsolidatedPolicy = newPolicy; diff --git a/services/core/java/com/android/server/om/IdmapManager.java b/services/core/java/com/android/server/om/IdmapManager.java index 25a39cc8456f..86d05d92c95b 100644 --- a/services/core/java/com/android/server/om/IdmapManager.java +++ b/services/core/java/com/android/server/om/IdmapManager.java @@ -257,7 +257,7 @@ final class IdmapManager { private boolean matchesActorSignature(@NonNull AndroidPackage targetPackage, @NonNull AndroidPackage overlayPackage, int userId) { String targetOverlayableName = overlayPackage.getOverlayTargetOverlayableName(); - if (targetOverlayableName != null) { + if (targetOverlayableName != null && !mPackageManager.getNamedActors().isEmpty()) { try { OverlayableInfo overlayableInfo = mPackageManager.getOverlayableForTarget( targetPackage.getPackageName(), targetOverlayableName, userId); diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java index b9464d96a019..a61b03fdbb39 100644 --- a/services/core/java/com/android/server/om/OverlayManagerService.java +++ b/services/core/java/com/android/server/om/OverlayManagerService.java @@ -32,6 +32,7 @@ import static android.os.Process.INVALID_UID; import static android.os.Trace.TRACE_TAG_RRO; import static android.os.Trace.traceBegin; import static android.os.Trace.traceEnd; + import static com.android.server.om.OverlayManagerServiceImpl.OperationFailedException; import android.annotation.NonNull; @@ -362,7 +363,7 @@ public final class OverlayManagerService extends SystemService { defaultPackages.add(packageName); } } - return defaultPackages.toArray(new String[defaultPackages.size()]); + return defaultPackages.toArray(new String[0]); } private final class OverlayManagerPackageMonitor extends PackageMonitor { @@ -1143,9 +1144,10 @@ public final class OverlayManagerService extends SystemService { }; private static final class PackageManagerHelperImpl implements PackageManagerHelper { - private static class PackageStateUsers { + private static final class PackageStateUsers { private PackageState mPackageState; - private final Set<Integer> mInstalledUsers = new ArraySet<>(); + private Boolean mDefinesOverlayable = null; + private final ArraySet<Integer> mInstalledUsers = new ArraySet<>(); private PackageStateUsers(@NonNull PackageState packageState) { this.mPackageState = packageState; } @@ -1160,7 +1162,7 @@ public final class OverlayManagerService extends SystemService { // state may lead to contradictions within OMS. Better then to lag // behind until all pending intents have been processed. private final ArrayMap<String, PackageStateUsers> mCache = new ArrayMap<>(); - private final Set<Integer> mInitializedUsers = new ArraySet<>(); + private final ArraySet<Integer> mInitializedUsers = new ArraySet<>(); PackageManagerHelperImpl(Context context) { mContext = context; @@ -1176,8 +1178,7 @@ public final class OverlayManagerService extends SystemService { */ @NonNull public ArrayMap<String, PackageState> initializeForUser(final int userId) { - if (!mInitializedUsers.contains(userId)) { - mInitializedUsers.add(userId); + if (mInitializedUsers.add(userId)) { mPackageManagerInternal.forEachPackageState((packageState -> { if (packageState.getPkg() != null && packageState.getUserStateOrDefault(userId).isInstalled()) { @@ -1196,13 +1197,11 @@ public final class OverlayManagerService extends SystemService { return userPackages; } - @Override - @Nullable - public PackageState getPackageStateForUser(@NonNull final String packageName, + private PackageStateUsers getRawPackageStateForUser(@NonNull final String packageName, final int userId) { final PackageStateUsers pkg = mCache.get(packageName); if (pkg != null && pkg.mInstalledUsers.contains(userId)) { - return pkg.mPackageState; + return pkg; } try { if (!mPackageManager.isPackageAvailable(packageName, userId)) { @@ -1216,8 +1215,14 @@ public final class OverlayManagerService extends SystemService { return addPackageUser(packageName, userId); } - @NonNull - private PackageState addPackageUser(@NonNull final String packageName, + @Override + public PackageState getPackageStateForUser(@NonNull final String packageName, + final int userId) { + final PackageStateUsers pkg = getRawPackageStateForUser(packageName, userId); + return pkg != null ? pkg.mPackageState : null; + } + + private PackageStateUsers addPackageUser(@NonNull final String packageName, final int user) { final PackageState pkg = mPackageManagerInternal.getPackageStateInternal(packageName); if (pkg == null) { @@ -1229,20 +1234,20 @@ public final class OverlayManagerService extends SystemService { } @NonNull - private PackageState addPackageUser(@NonNull final PackageState pkg, + private PackageStateUsers addPackageUser(@NonNull final PackageState pkg, final int user) { PackageStateUsers pkgUsers = mCache.get(pkg.getPackageName()); if (pkgUsers == null) { pkgUsers = new PackageStateUsers(pkg); mCache.put(pkg.getPackageName(), pkgUsers); - } else { + } else if (pkgUsers.mPackageState != pkg) { pkgUsers.mPackageState = pkg; + pkgUsers.mDefinesOverlayable = null; } pkgUsers.mInstalledUsers.add(user); - return pkgUsers.mPackageState; + return pkgUsers; } - @NonNull private void removePackageUser(@NonNull final String packageName, final int user) { final PackageStateUsers pkgUsers = mCache.get(packageName); @@ -1260,15 +1265,15 @@ public final class OverlayManagerService extends SystemService { } } - @Nullable public PackageState onPackageAdded(@NonNull final String packageName, final int userId) { - return addPackageUser(packageName, userId); + final var pu = addPackageUser(packageName, userId); + return pu != null ? pu.mPackageState : null; } - @Nullable public PackageState onPackageUpdated(@NonNull final String packageName, final int userId) { - return addPackageUser(packageName, userId); + final var pu = addPackageUser(packageName, userId); + return pu != null ? pu.mPackageState : null; } public void onPackageRemoved(@NonNull final String packageName, final int userId) { @@ -1308,22 +1313,30 @@ public final class OverlayManagerService extends SystemService { return (pkgs.length == 0) ? null : pkgs[0]; } - @Nullable @Override public OverlayableInfo getOverlayableForTarget(@NonNull String packageName, @NonNull String targetOverlayableName, int userId) throws IOException { - var packageState = getPackageStateForUser(packageName, userId); - var pkg = packageState == null ? null : packageState.getAndroidPackage(); + final var psu = getRawPackageStateForUser(packageName, userId); + final var pkg = (psu == null || psu.mPackageState == null) + ? null : psu.mPackageState.getAndroidPackage(); if (pkg == null) { throw new IOException("Unable to get target package"); } + if (Boolean.FALSE.equals(psu.mDefinesOverlayable)) { + return null; + } + ApkAssets apkAssets = null; try { apkAssets = ApkAssets.loadFromPath(pkg.getSplits().get(0).getPath(), ApkAssets.PROPERTY_ONLY_OVERLAYABLES); - return apkAssets.getOverlayableInfo(targetOverlayableName); + if (psu.mDefinesOverlayable == null) { + psu.mDefinesOverlayable = apkAssets.definesOverlayable(); + } + return Boolean.FALSE.equals(psu.mDefinesOverlayable) + ? null : apkAssets.getOverlayableInfo(targetOverlayableName); } finally { if (apkAssets != null) { try { @@ -1337,24 +1350,29 @@ public final class OverlayManagerService extends SystemService { @Override public boolean doesTargetDefineOverlayable(String targetPackageName, int userId) throws IOException { - var packageState = getPackageStateForUser(targetPackageName, userId); - var pkg = packageState == null ? null : packageState.getAndroidPackage(); + final var psu = getRawPackageStateForUser(targetPackageName, userId); + var pkg = (psu == null || psu.mPackageState == null) + ? null : psu.mPackageState.getAndroidPackage(); if (pkg == null) { throw new IOException("Unable to get target package"); } - ApkAssets apkAssets = null; - try { - apkAssets = ApkAssets.loadFromPath(pkg.getSplits().get(0).getPath()); - return apkAssets.definesOverlayable(); - } finally { - if (apkAssets != null) { - try { - apkAssets.close(); - } catch (Throwable ignored) { + if (psu.mDefinesOverlayable == null) { + ApkAssets apkAssets = null; + try { + apkAssets = ApkAssets.loadFromPath(pkg.getSplits().get(0).getPath(), + ApkAssets.PROPERTY_ONLY_OVERLAYABLES); + psu.mDefinesOverlayable = apkAssets.definesOverlayable(); + } finally { + if (apkAssets != null) { + try { + apkAssets.close(); + } catch (Throwable ignored) { + } } } } + return psu.mDefinesOverlayable; } @Override @@ -1545,8 +1563,7 @@ public final class OverlayManagerService extends SystemService { final OverlayPaths frameworkOverlays = mImpl.getEnabledOverlayPaths("android", userId, false); for (final String targetPackageName : targetPackageNames) { - final OverlayPaths.Builder list = new OverlayPaths.Builder(); - list.addAll(frameworkOverlays); + final var list = new OverlayPaths.Builder(frameworkOverlays); if (!"android".equals(targetPackageName)) { list.addAll(mImpl.getEnabledOverlayPaths(targetPackageName, userId, true)); } @@ -1558,17 +1575,21 @@ public final class OverlayManagerService extends SystemService { final HashSet<String> invalidPackages = new HashSet<>(); pm.setEnabledOverlayPackages(userId, pendingChanges, updatedPackages, invalidPackages); - for (final String targetPackageName : targetPackageNames) { - if (DEBUG) { - Slog.d(TAG, "-> Updating overlay: target=" + targetPackageName + " overlays=[" - + pendingChanges.get(targetPackageName) - + "] userId=" + userId); - } + if (DEBUG || !invalidPackages.isEmpty()) { + for (final String targetPackageName : targetPackageNames) { + if (DEBUG) { + Slog.d(TAG, + "-> Updating overlay: target=" + targetPackageName + " overlays=[" + + pendingChanges.get(targetPackageName) + + "] userId=" + userId); + } - if (invalidPackages.contains(targetPackageName)) { - Slog.e(TAG, TextUtils.formatSimple( - "Failed to change enabled overlays for %s user %d", targetPackageName, - userId)); + if (invalidPackages.contains(targetPackageName)) { + Slog.e(TAG, TextUtils.formatSimple( + "Failed to change enabled overlays for %s user %d", + targetPackageName, + userId)); + } } } return new ArrayList<>(updatedPackages); diff --git a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java index 972c78db9460..c1b6ccc7e25c 100644 --- a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java +++ b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java @@ -772,24 +772,20 @@ final class OverlayManagerServiceImpl { OverlayPaths getEnabledOverlayPaths(@NonNull final String targetPackageName, final int userId, boolean includeImmutableOverlays) { - final List<OverlayInfo> overlays = mSettings.getOverlaysForTarget(targetPackageName, - userId); - final OverlayPaths.Builder paths = new OverlayPaths.Builder(); - final int n = overlays.size(); - for (int i = 0; i < n; i++) { - final OverlayInfo oi = overlays.get(i); + final var paths = new OverlayPaths.Builder(); + mSettings.forEachMatching(userId, null, targetPackageName, oi -> { if (!oi.isEnabled()) { - continue; + return; } if (!includeImmutableOverlays && !oi.isMutable) { - continue; + return; } if (oi.isFabricated()) { paths.addNonApkPath(oi.baseCodePath); } else { paths.addApkPath(oi.baseCodePath); } - } + }); return paths.build(); } diff --git a/services/core/java/com/android/server/om/OverlayManagerSettings.java b/services/core/java/com/android/server/om/OverlayManagerSettings.java index eae614ac9e77..b8b49f3eed2f 100644 --- a/services/core/java/com/android/server/om/OverlayManagerSettings.java +++ b/services/core/java/com/android/server/om/OverlayManagerSettings.java @@ -47,6 +47,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.Set; +import java.util.function.Consumer; import java.util.function.Predicate; import java.util.stream.Stream; @@ -182,6 +183,23 @@ final class OverlayManagerSettings { return CollectionUtils.map(items, SettingsItem::getOverlayInfo); } + void forEachMatching(int userId, String overlayName, String targetPackageName, + @NonNull Consumer<OverlayInfo> consumer) { + for (int i = 0, n = mItems.size(); i < n; i++) { + final SettingsItem item = mItems.get(i); + if (item.getUserId() != userId) { + continue; + } + if (overlayName != null && !item.mOverlay.getPackageName().equals(overlayName)) { + continue; + } + if (targetPackageName != null && !item.mTargetPackageName.equals(targetPackageName)) { + continue; + } + consumer.accept(item.getOverlayInfo()); + } + } + ArrayMap<String, List<OverlayInfo>> getOverlaysForUser(final int userId) { final List<SettingsItem> items = selectWhereUser(userId); diff --git a/services/core/java/com/android/server/pm/AppsFilterImpl.java b/services/core/java/com/android/server/pm/AppsFilterImpl.java index f3df4244c47f..cc4c2b5bf893 100644 --- a/services/core/java/com/android/server/pm/AppsFilterImpl.java +++ b/services/core/java/com/android/server/pm/AppsFilterImpl.java @@ -1031,12 +1031,12 @@ public final class AppsFilterImpl extends AppsFilterLocked implements Watchable, private void recomputeComponentVisibility( ArrayMap<String, ? extends PackageStateInternal> existingSettings) { final WatchedArraySet<String> protectedBroadcasts; - final WatchedArraySet<Integer> forceQueryable; + final ArraySet<Integer> forceQueryable; synchronized (mProtectedBroadcastsLock) { - protectedBroadcasts = mProtectedBroadcasts.snapshot(); + protectedBroadcasts = new WatchedArraySet<String>(mProtectedBroadcasts); } synchronized (mForceQueryableLock) { - forceQueryable = mForceQueryable.snapshot(); + forceQueryable = new ArraySet<Integer>(mForceQueryable.untrackedStorage()); } final ParallelComputeComponentVisibility computer = new ParallelComputeComponentVisibility( existingSettings, forceQueryable, protectedBroadcasts); diff --git a/services/core/java/com/android/server/pm/AppsFilterUtils.java b/services/core/java/com/android/server/pm/AppsFilterUtils.java index 200734b37269..a02a1bc13b17 100644 --- a/services/core/java/com/android/server/pm/AppsFilterUtils.java +++ b/services/core/java/com/android/server/pm/AppsFilterUtils.java @@ -198,12 +198,12 @@ final class AppsFilterUtils { private static final int MAX_THREADS = 4; private final ArrayMap<String, ? extends PackageStateInternal> mExistingSettings; - private final WatchedArraySet<Integer> mForceQueryable; + private final ArraySet<Integer> mForceQueryable; private final WatchedArraySet<String> mProtectedBroadcasts; ParallelComputeComponentVisibility( @NonNull ArrayMap<String, ? extends PackageStateInternal> existingSettings, - @NonNull WatchedArraySet<Integer> forceQueryable, + @NonNull ArraySet<Integer> forceQueryable, @NonNull WatchedArraySet<String> protectedBroadcasts) { mExistingSettings = existingSettings; mForceQueryable = forceQueryable; diff --git a/services/core/java/com/android/server/pm/BackgroundInstallControlService.java b/services/core/java/com/android/server/pm/BackgroundInstallControlService.java index c110fb67b54f..200b17bc2f97 100644 --- a/services/core/java/com/android/server/pm/BackgroundInstallControlService.java +++ b/services/core/java/com/android/server/pm/BackgroundInstallControlService.java @@ -16,7 +16,12 @@ package com.android.server.pm; +import static android.Manifest.permission.GET_BACKGROUND_INSTALLED_PACKAGES; +import static android.content.pm.PackageManager.PERMISSION_GRANTED; + import android.annotation.NonNull; +import android.annotation.RequiresPermission; +import android.app.Flags; import android.app.usage.UsageEvents; import android.app.usage.UsageStatsManagerInternal; import android.content.Context; @@ -27,6 +32,7 @@ import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; import android.content.pm.ParceledListSlice; +import android.os.Binder; import android.os.Build; import android.os.Environment; import android.os.Handler; @@ -69,26 +75,29 @@ public class BackgroundInstallControlService extends SystemService { private static final String DISK_FILE_NAME = "states"; private static final String DISK_DIR_NAME = "bic"; - private static final int MAX_FOREGROUND_TIME_FRAMES_SIZE = 10; + private static final String ENFORCE_PERMISSION_ERROR_MSG = + "User is not permitted to call service: "; + private static final int MAX_FOREGROUND_TIME_FRAMES_SIZE = 10; private static final int MSG_USAGE_EVENT_RECEIVED = 0; private static final int MSG_PACKAGE_ADDED = 1; private static final int MSG_PACKAGE_REMOVED = 2; private final BinderService mBinderService; private final PackageManager mPackageManager; + // TODO migrate all internal PackageManager calls to PackageManagerInternal where possible. + // b/310983905 private final PackageManagerInternal mPackageManagerInternal; private final PermissionManagerServiceInternal mPermissionManager; private final Handler mHandler; private final File mDiskFile; - + private final Context mContext; private SparseSetArray<String> mBackgroundInstalledPackages = null; // User ID -> package name -> set of foreground time frame - private final SparseArrayMap<String, - TreeSet<ForegroundTimeFrame>> mInstallerForegroundTimeFrames = - new SparseArrayMap<>(); + private final SparseArrayMap<String, TreeSet<ForegroundTimeFrame>> + mInstallerForegroundTimeFrames = new SparseArrayMap<>(); public BackgroundInstallControlService(@NonNull Context context) { this(new InjectorImpl(context)); @@ -102,15 +111,13 @@ public class BackgroundInstallControlService extends SystemService { mPermissionManager = injector.getPermissionManager(); mHandler = new EventHandler(injector.getLooper(), this); mDiskFile = injector.getDiskFile(); + mContext = injector.getContext(); UsageStatsManagerInternal usageStatsManagerInternal = injector.getUsageStatsManagerInternal(); usageStatsManagerInternal.registerListener( (userId, event) -> - mHandler.obtainMessage(MSG_USAGE_EVENT_RECEIVED, - userId, - 0, - event).sendToTarget() - ); + mHandler.obtainMessage(MSG_USAGE_EVENT_RECEIVED, userId, 0, event) + .sendToTarget()); mBinderService = new BinderService(this); } @@ -124,12 +131,17 @@ public class BackgroundInstallControlService extends SystemService { @Override public ParceledListSlice<PackageInfo> getBackgroundInstalledPackages( @PackageManager.PackageInfoFlagsBits long flags, int userId) { + if (Flags.bicClient()) { + mService.enforceCallerPermissions(); + } if (!Build.IS_DEBUGGABLE) { return mService.getBackgroundInstalledPackages(flags, userId); } // The debug.transparency.bg-install-apps (only works for debuggable builds) // is used to set mock list of background installed apps for testing. // The list of apps' names is delimited by ",". + // TODO: Remove after migrating test to new background install method using + // {@link BackgroundInstallControlCallbackHelperTest}.installPackage b/310983905 String propertyString = SystemProperties.get("debug.transparency.bg-install-apps"); if (TextUtils.isEmpty(propertyString)) { return mService.getBackgroundInstalledPackages(flags, userId); @@ -137,25 +149,36 @@ public class BackgroundInstallControlService extends SystemService { return mService.getMockBackgroundInstalledPackages(propertyString); } } + + } + + @RequiresPermission(GET_BACKGROUND_INSTALLED_PACKAGES) + void enforceCallerPermissions() throws SecurityException { + mContext.enforceCallingOrSelfPermission(GET_BACKGROUND_INSTALLED_PACKAGES, + ENFORCE_PERMISSION_ERROR_MSG + GET_BACKGROUND_INSTALLED_PACKAGES); } @VisibleForTesting ParceledListSlice<PackageInfo> getBackgroundInstalledPackages( @PackageManager.PackageInfoFlagsBits long flags, int userId) { - List<PackageInfo> packages = mPackageManager.getInstalledPackagesAsUser( + final long token = Binder.clearCallingIdentity(); + try { + List<PackageInfo> packages = mPackageManager.getInstalledPackagesAsUser( PackageManager.PackageInfoFlags.of(flags), userId); - initBackgroundInstalledPackages(); - - ListIterator<PackageInfo> iter = packages.listIterator(); - while (iter.hasNext()) { - String packageName = iter.next().packageName; - if (!mBackgroundInstalledPackages.contains(userId, packageName)) { - iter.remove(); + initBackgroundInstalledPackages(); + ListIterator<PackageInfo> iter = packages.listIterator(); + while (iter.hasNext()) { + String packageName = iter.next().packageName; + if (!mBackgroundInstalledPackages.contains(userId, packageName)) { + iter.remove(); + } } - } - return new ParceledListSlice<>(packages); + return new ParceledListSlice<>(packages); + } finally { + Binder.restoreCallingIdentity(token); + } } /** @@ -168,8 +191,9 @@ public class BackgroundInstallControlService extends SystemService { List<PackageInfo> mockPackages = new ArrayList<>(); for (String name : mockPackageNames) { try { - PackageInfo packageInfo = mPackageManager.getPackageInfo(name, - PackageManager.PackageInfoFlags.of(PackageManager.MATCH_ALL)); + PackageInfo packageInfo = + mPackageManager.getPackageInfo( + name, PackageManager.PackageInfoFlags.of(PackageManager.MATCH_ALL)); mockPackages.add(packageInfo); } catch (PackageManager.NameNotFoundException e) { Slog.w(TAG, "Package's PackageInfo not found " + name); @@ -190,18 +214,16 @@ public class BackgroundInstallControlService extends SystemService { @Override public void handleMessage(Message msg) { switch (msg.what) { - case MSG_USAGE_EVENT_RECEIVED: { - mService.handleUsageEvent((UsageEvents.Event) msg.obj, msg.arg1 /* userId */); + case MSG_USAGE_EVENT_RECEIVED: + mService.handleUsageEvent( + (UsageEvents.Event) msg.obj, msg.arg1 /* userId */); break; - } - case MSG_PACKAGE_ADDED: { + case MSG_PACKAGE_ADDED: mService.handlePackageAdd((String) msg.obj, msg.arg1 /* userId */); break; - } - case MSG_PACKAGE_REMOVED: { + case MSG_PACKAGE_REMOVED: mService.handlePackageRemove((String) msg.obj, msg.arg1 /* userId */); break; - } default: Slog.w(TAG, "Unknown message: " + msg.what); } @@ -211,8 +233,9 @@ public class BackgroundInstallControlService extends SystemService { void handlePackageAdd(String packageName, int userId) { ApplicationInfo appInfo = null; try { - appInfo = mPackageManager.getApplicationInfoAsUser(packageName, - PackageManager.ApplicationInfoFlags.of(0), userId); + appInfo = + mPackageManager.getApplicationInfoAsUser( + packageName, PackageManager.ApplicationInfoFlags.of(0), userId); } catch (PackageManager.NameNotFoundException e) { Slog.w(TAG, "Package's appInfo not found " + packageName); return; @@ -231,15 +254,18 @@ public class BackgroundInstallControlService extends SystemService { // the installers without INSTALL_PACKAGES perm can't perform // the installation in background. So we can just filter out them. - if (mPermissionManager.checkPermission(installerPackageName, - android.Manifest.permission.INSTALL_PACKAGES, Context.DEVICE_ID_DEFAULT, - userId) != PackageManager.PERMISSION_GRANTED) { + if (mPermissionManager.checkPermission( + installerPackageName, + android.Manifest.permission.INSTALL_PACKAGES, + Context.DEVICE_ID_DEFAULT, + userId) + != PERMISSION_GRANTED) { return; } // convert up-time to current time. - final long installTimestamp = System.currentTimeMillis() - - (SystemClock.uptimeMillis() - appInfo.createTimestamp); + final long installTimestamp = + System.currentTimeMillis() - (SystemClock.uptimeMillis() - appInfo.createTimestamp); if (installedByAdb(initiatingPackageName) || wasForegroundInstallation(installerPackageName, userId, installTimestamp)) { @@ -257,8 +283,8 @@ public class BackgroundInstallControlService extends SystemService { return PackageManagerServiceUtils.isInstalledByAdb(initiatingPackageName); } - private boolean wasForegroundInstallation(String installerPackageName, - int userId, long installTimestamp) { + private boolean wasForegroundInstallation( + String installerPackageName, int userId, long installTimestamp) { TreeSet<BackgroundInstallControlService.ForegroundTimeFrame> foregroundTimeFrames = mInstallerForegroundTimeFrames.get(userId, installerPackageName); @@ -347,12 +373,12 @@ public class BackgroundInstallControlService extends SystemService { for (int i = 0; i < mBackgroundInstalledPackages.size(); i++) { int userId = mBackgroundInstalledPackages.keyAt(i); for (String packageName : mBackgroundInstalledPackages.get(userId)) { - long token = protoOutputStream.start( - BackgroundInstalledPackagesProto.BG_INSTALLED_PKG); + long token = + protoOutputStream.start( + BackgroundInstalledPackagesProto.BG_INSTALLED_PKG); protoOutputStream.write( BackgroundInstalledPackageProto.PACKAGE_NAME, packageName); - protoOutputStream.write( - BackgroundInstalledPackageProto.USER_ID, userId + 1); + protoOutputStream.write(BackgroundInstalledPackageProto.USER_ID, userId + 1); protoOutputStream.end(token); } } @@ -385,23 +411,28 @@ public class BackgroundInstallControlService extends SystemService { != (int) BackgroundInstalledPackagesProto.BG_INSTALLED_PKG) { continue; } - long token = protoInputStream.start( - BackgroundInstalledPackagesProto.BG_INSTALLED_PKG); + long token = + protoInputStream.start(BackgroundInstalledPackagesProto.BG_INSTALLED_PKG); String packageName = null; int userId = UserHandle.USER_NULL; while (protoInputStream.nextField() != ProtoInputStream.NO_MORE_FIELDS) { switch (protoInputStream.getFieldNumber()) { case (int) BackgroundInstalledPackageProto.PACKAGE_NAME: - packageName = protoInputStream.readString( - BackgroundInstalledPackageProto.PACKAGE_NAME); + packageName = + protoInputStream.readString( + BackgroundInstalledPackageProto.PACKAGE_NAME); break; case (int) BackgroundInstalledPackageProto.USER_ID: - userId = protoInputStream.readInt( - BackgroundInstalledPackageProto.USER_ID) - 1; + userId = + protoInputStream.readInt( + BackgroundInstalledPackageProto.USER_ID) + - 1; break; default: - Slog.w(TAG, "Undefined field in proto: " - + protoInputStream.getFieldNumber()); + Slog.w( + TAG, + "Undefined field in proto: " + + protoInputStream.getFieldNumber()); } } protoInputStream.end(token); @@ -430,9 +461,12 @@ public class BackgroundInstallControlService extends SystemService { if (mInstallerForegroundTimeFrames.contains(userId, pkgName)) { return true; } - return mPermissionManager.checkPermission(pkgName, - android.Manifest.permission.INSTALL_PACKAGES, Context.DEVICE_ID_DEFAULT, - userId) == PackageManager.PERMISSION_GRANTED; + return mPermissionManager.checkPermission( + pkgName, + android.Manifest.permission.INSTALL_PACKAGES, + Context.DEVICE_ID_DEFAULT, + userId) + == PERMISSION_GRANTED; } @Override @@ -446,21 +480,22 @@ public class BackgroundInstallControlService extends SystemService { publishBinderService(Context.BACKGROUND_INSTALL_CONTROL_SERVICE, mBinderService); } - mPackageManagerInternal.getPackageList(new PackageManagerInternal.PackageListObserver() { - @Override - public void onPackageAdded(String packageName, int uid) { - final int userId = UserHandle.getUserId(uid); - mHandler.obtainMessage(MSG_PACKAGE_ADDED, - userId, 0, packageName).sendToTarget(); - } + mPackageManagerInternal.getPackageList( + new PackageManagerInternal.PackageListObserver() { + @Override + public void onPackageAdded(String packageName, int uid) { + final int userId = UserHandle.getUserId(uid); + mHandler.obtainMessage(MSG_PACKAGE_ADDED, userId, 0, packageName) + .sendToTarget(); + } - @Override - public void onPackageRemoved(String packageName, int uid) { - final int userId = UserHandle.getUserId(uid); - mHandler.obtainMessage(MSG_PACKAGE_REMOVED, - userId, 0, packageName).sendToTarget(); - } - }); + @Override + public void onPackageRemoved(String packageName, int uid) { + final int userId = UserHandle.getUserId(uid); + mHandler.obtainMessage(MSG_PACKAGE_REMOVED, userId, 0, packageName) + .sendToTarget(); + } + }); } // The foreground time frame (ForegroundTimeFrame) represents the period @@ -516,7 +551,7 @@ public class BackgroundInstallControlService extends SystemService { } /** - * Dependency injector for {@link #BackgroundInstallControlService)}. + * Dependency injector for {@link BackgroundInstallControlService}. */ interface Injector { Context getContext(); @@ -532,6 +567,7 @@ public class BackgroundInstallControlService extends SystemService { Looper getLooper(); File getDiskFile(); + } private static final class InjectorImpl implements Injector { @@ -568,11 +604,11 @@ public class BackgroundInstallControlService extends SystemService { @Override public Looper getLooper() { - ServiceThread serviceThread = new ServiceThread(TAG, - android.os.Process.THREAD_PRIORITY_FOREGROUND, true /* allowIo */); + ServiceThread serviceThread = + new ServiceThread( + TAG, android.os.Process.THREAD_PRIORITY_FOREGROUND, true /* allowIo */); serviceThread.start(); return serviceThread.getLooper(); - } @Override diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java index 92be4ee3acd9..f311034a4dd2 100644 --- a/services/core/java/com/android/server/pm/InstallPackageHelper.java +++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java @@ -576,6 +576,12 @@ final class InstallPackageHelper { mApexManager.registerApkInApex(pkg); } + if ((mPm.isDeviceUpgrading() && pkgSetting.isSystem()) || isReplace) { + for (int userId : mPm.mUserManager.getUserIds()) { + pkgSetting.restoreComponentSettings(userId); + } + } + // Don't add keysets for APEX as their package settings are not persisted and will // result in orphaned keysets. if ((scanFlags & SCAN_AS_APEX) == 0) { @@ -2894,6 +2900,12 @@ final class InstallPackageHelper { // code is loaded by a new Activity before ApplicationInfo changes have // propagated to all application threads. mPm.scheduleDeferredNoKillPostDelete(args); + if (Flags.improveInstallDontKill()) { + synchronized (mPm.mInstallLock) { + PackageManagerServiceUtils.linkSplitsToOldDirs(mPm.mInstaller, + packageName, pkgSetting.getPath(), pkgSetting.getOldPaths()); + } + } } else { mRemovePackageHelper.cleanUpResources(packageName, args.getCodeFile(), args.getInstructionSets()); diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java index ac826afc1d22..b5346a351f38 100644 --- a/services/core/java/com/android/server/pm/LauncherAppsService.java +++ b/services/core/java/com/android/server/pm/LauncherAppsService.java @@ -1680,9 +1680,8 @@ public class LauncherAppsService extends SystemService { mContext, /* requestCode */ 0, intent, - PendingIntent.FLAG_ONE_SHOT - | PendingIntent.FLAG_IMMUTABLE - | PendingIntent.FLAG_CANCEL_CURRENT, + PendingIntent.FLAG_IMMUTABLE + | FLAG_UPDATE_CURRENT, /* options */ null, user); return pi == null ? null : pi.getIntentSender(); diff --git a/services/core/java/com/android/server/pm/PackageArchiver.java b/services/core/java/com/android/server/pm/PackageArchiver.java index 09a91eda483a..32f56463c8de 100644 --- a/services/core/java/com/android/server/pm/PackageArchiver.java +++ b/services/core/java/com/android/server/pm/PackageArchiver.java @@ -31,6 +31,7 @@ import static android.content.pm.PackageInstaller.UNARCHIVAL_STATUS_UNSET; import static android.content.pm.PackageManager.DELETE_ARCHIVE; import static android.content.pm.PackageManager.DELETE_KEEP_DATA; import static android.content.pm.PackageManager.INSTALL_UNARCHIVE_DRAFT; +import static android.graphics.drawable.AdaptiveIconDrawable.getExtraInsetFraction; import static android.os.PowerExemptionManager.REASON_PACKAGE_UNARCHIVE; import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED; @@ -66,8 +67,11 @@ import android.graphics.BitmapFactory; import android.graphics.Color; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; +import android.graphics.drawable.AdaptiveIconDrawable; import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; +import android.graphics.drawable.InsetDrawable; import android.graphics.drawable.LayerDrawable; import android.os.Binder; import android.os.Bundle; @@ -191,6 +195,7 @@ public class PackageArchiver { Computer snapshot = mPm.snapshotComputer(); int userId = userHandle.getIdentifier(); int binderUid = Binder.getCallingUid(); + int binderPid = Binder.getCallingPid(); if (!PackageManagerServiceUtils.isSystemOrRootOrShell(binderUid)) { verifyCaller(snapshot.getPackageUid(callerPackageName, 0, userId), binderUid); } @@ -225,7 +230,8 @@ public class PackageArchiver { DELETE_ARCHIVE | DELETE_KEEP_DATA, intentSender, userId, - binderUid); + binderUid, + binderPid); }) .exceptionally( e -> { @@ -379,9 +385,8 @@ public class PackageArchiver { verifyNotSystemApp(ps.getFlags()); verifyInstalled(ps, userId); String responsibleInstallerPackage = getResponsibleInstallerPackage(ps); - verifyInstaller(responsibleInstallerPackage, userId); - ApplicationInfo installerInfo = snapshot.getApplicationInfo( - responsibleInstallerPackage, /* flags= */ 0, userId); + ApplicationInfo installerInfo = verifyInstaller( + snapshot, responsibleInstallerPackage, userId); verifyOptOutStatus(packageName, UserHandle.getUid(userId, UserHandle.getUid(userId, ps.getAppId()))); @@ -421,10 +426,10 @@ public class PackageArchiver { List<ArchiveActivityInfo> archiveActivityInfos = new ArrayList<>(mainActivities.size()); for (int i = 0, size = mainActivities.size(); i < size; ++i) { var mainActivity = mainActivities.get(i); - Path iconPath = storeDrawable( - packageName, mainActivity.getIcon(), userId, i, iconSize); - Path monochromePath = storeDrawable( - packageName, mainActivity.getMonochromeIcon(), userId, i, iconSize); + Path iconPath = storeAdaptiveDrawable( + packageName, mainActivity.getIcon(), userId, i * 2 + 0, iconSize); + Path monochromePath = storeAdaptiveDrawable( + packageName, mainActivity.getMonochromeIcon(), userId, i * 2 + 1, iconSize); ArchiveActivityInfo activityInfo = new ArchiveActivityInfo( mainActivity.getLabel().toString(), @@ -451,7 +456,8 @@ public class PackageArchiver { List<ArchiveActivityInfo> archiveActivityInfos = new ArrayList<>(mainActivities.size()); for (int i = 0, size = mainActivities.size(); i < size; i++) { LauncherActivityInfo mainActivity = mainActivities.get(i); - Path iconPath = storeIcon(packageName, mainActivity, userId, i, iconSize); + Path iconPath = storeIcon(packageName, mainActivity, userId, i * 2 + 0, iconSize); + // i * 2 + 1 reserved for monochromeIcon ArchiveActivityInfo activityInfo = new ArchiveActivityInfo( mainActivity.getLabel().toString(), @@ -495,8 +501,30 @@ public class PackageArchiver { return iconFile.toPath(); } - private void verifyInstaller(String installerPackageName, int userId) - throws PackageManager.NameNotFoundException { + /** + * Create an <a + * href="https://developer.android.com/develop/ui/views/launch/icon_design_adaptive"> + * adaptive icon</a> from an icon. + * This is necessary so the icon can be displayed properly by different launchers. + */ + private static Path storeAdaptiveDrawable(String packageName, @Nullable Drawable iconDrawable, + @UserIdInt int userId, int index, int iconSize) throws IOException { + if (iconDrawable == null) { + return null; + } + + // see BaseIconFactory#createShapedIconBitmap + float inset = getExtraInsetFraction(); + inset = inset / (1 + 2 * inset); + Drawable d = new AdaptiveIconDrawable(new ColorDrawable(Color.BLACK), + new InsetDrawable(iconDrawable/*d*/, inset, inset, inset, inset)); + + return storeDrawable(packageName, d, userId, index, iconSize); + } + + + private ApplicationInfo verifyInstaller(Computer snapshot, String installerPackageName, + int userId) throws PackageManager.NameNotFoundException { if (TextUtils.isEmpty(installerPackageName)) { throw new PackageManager.NameNotFoundException("No installer found"); } @@ -505,6 +533,12 @@ public class PackageArchiver { && !verifySupportsUnarchival(installerPackageName, userId)) { throw new PackageManager.NameNotFoundException("Installer does not support unarchival"); } + ApplicationInfo appInfo = snapshot.getApplicationInfo( + installerPackageName, /* flags=*/ 0, userId); + if (appInfo == null) { + throw new PackageManager.NameNotFoundException("Failed to obtain Installer info"); + } + return appInfo; } /** @@ -570,7 +604,7 @@ public class PackageArchiver { } try { - verifyInstaller(getResponsibleInstallerPackage(ps), userId); + verifyInstaller(snapshot, getResponsibleInstallerPackage(ps), userId); getLauncherActivityInfos(packageName, userId); } catch (PackageManager.NameNotFoundException e) { return false; diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java index 7bf9fe7aa7e2..c6d448d97673 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerService.java +++ b/services/core/java/com/android/server/pm/PackageInstallerService.java @@ -788,6 +788,24 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements } } + if (Flags.recoverabilityDetection()) { + if (params.rollbackImpactLevel == PackageManager.ROLLBACK_USER_IMPACT_HIGH + || params.rollbackImpactLevel + == PackageManager.ROLLBACK_USER_IMPACT_ONLY_MANUAL) { + if ((params.installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) == 0) { + throw new IllegalArgumentException( + "Can't set rollbackImpactLevel when rollback is not enabled"); + } + if (mContext.checkCallingOrSelfPermission(Manifest.permission.MANAGE_ROLLBACKS) + != PackageManager.PERMISSION_GRANTED) { + throw new SecurityException( + "Setting rollbackImpactLevel requires the MANAGE_ROLLBACKS permission"); + } + } else if (params.rollbackImpactLevel < 0) { + throw new IllegalArgumentException("rollbackImpactLevel can't be negative."); + } + } + boolean isApex = (params.installFlags & PackageManager.INSTALL_APEX) != 0; if (isApex) { if (mContext.checkCallingOrSelfPermission(Manifest.permission.INSTALL_PACKAGE_UPDATES) @@ -1387,11 +1405,12 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements flags, statusReceiver, userId, - Binder.getCallingUid()); + Binder.getCallingUid(), + Binder.getCallingPid()); } void uninstall(VersionedPackage versionedPackage, String callerPackageName, int flags, - IntentSender statusReceiver, int userId, int callingUid) { + IntentSender statusReceiver, int userId, int callingUid, int callingPid) { final Computer snapshot = mPm.snapshotComputer(); snapshot.enforceCrossUserPermission(callingUid, userId, true, true, "uninstall"); if (!PackageManagerServiceUtils.isRootOrShell(callingUid)) { @@ -1408,7 +1427,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements final PackageDeleteObserverAdapter adapter = new PackageDeleteObserverAdapter(mContext, statusReceiver, versionedPackage.getPackageName(), canSilentlyInstallPackage, userId, mPackageArchiver, flags); - if (mContext.checkCallingOrSelfPermission(Manifest.permission.DELETE_PACKAGES) + if (mContext.checkPermission(Manifest.permission.DELETE_PACKAGES, callingPid, callingUid) == PackageManager.PERMISSION_GRANTED) { // Sweet, call straight through! mPm.deletePackageVersioned(versionedPackage, adapter.getBinder(), userId, flags); @@ -1428,8 +1447,8 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements } else { ApplicationInfo appInfo = snapshot.getApplicationInfo(callerPackageName, 0, userId); if (appInfo.targetSdkVersion >= Build.VERSION_CODES.P) { - mContext.enforceCallingOrSelfPermission(Manifest.permission.REQUEST_DELETE_PACKAGES, - null); + mContext.enforcePermission(Manifest.permission.REQUEST_DELETE_PACKAGES, callingPid, + callingUid, null); } // Take a short detour to confirm with user diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index 117d03fd059b..27c3dad23450 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerSession.java +++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java @@ -54,6 +54,7 @@ import static com.android.internal.util.XmlUtils.writeStringAttribute; import static com.android.internal.util.XmlUtils.writeUriAttribute; import static com.android.server.pm.PackageInstallerService.prepareStageDir; import static com.android.server.pm.PackageManagerService.APP_METADATA_FILE_NAME; +import static com.android.server.pm.PackageManagerService.DEFAULT_FILE_ACCESS_MODE; import static com.android.server.pm.PackageManagerServiceUtils.isInstalledByAdb; import static com.android.server.pm.PackageManagerShellCommandDataLoader.Metadata; @@ -1294,6 +1295,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { info.autoRevokePermissionsMode = params.autoRevokePermissionsMode; info.installFlags = params.installFlags; info.rollbackLifetimeMillis = params.rollbackLifetimeMillis; + info.rollbackImpactLevel = params.rollbackImpactLevel; info.isMultiPackage = params.isMultiPackage; info.isStaged = params.isStaged; info.rollbackDataPolicy = params.rollbackDataPolicy; @@ -1831,7 +1833,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { try { Os.link(path, sourcePath); // Grant READ access for APK to be read successfully - Os.chmod(sourcePath, 0644); + Os.chmod(sourcePath, DEFAULT_FILE_ACCESS_MODE); } catch (ErrnoException e) { e.rethrowAsIOException(); } @@ -1900,7 +1902,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { // If file is app metadata then set permission to 0640 to deny user read access since it // might contain sensitive information. - int mode = name.equals(APP_METADATA_FILE_NAME) ? APP_METADATA_FILE_ACCESS_MODE : 0644; + int mode = name.equals(APP_METADATA_FILE_NAME) + ? APP_METADATA_FILE_ACCESS_MODE : DEFAULT_FILE_ACCESS_MODE; ParcelFileDescriptor targetPfd = openTargetInternal(target.getAbsolutePath(), O_CREAT | O_WRONLY, mode); Os.chmod(target.getAbsolutePath(), mode); @@ -4245,7 +4248,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { throw new IOException("Failed to copy " + fromFile + " to " + tmpFile); } try { - Os.chmod(tmpFile.getAbsolutePath(), 0644); + Os.chmod(tmpFile.getAbsolutePath(), DEFAULT_FILE_ACCESS_MODE); } catch (ErrnoException e) { throw new IOException("Failed to chmod " + tmpFile); } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index c5b5a761497d..46f55238163c 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -593,6 +593,8 @@ public class PackageManagerService implements PackageSender, TestUtilityService static final String APP_METADATA_FILE_NAME = "app.metadata"; + static final int DEFAULT_FILE_ACCESS_MODE = 0644; + final Handler mHandler; final Handler mBackgroundHandler; @@ -4334,11 +4336,11 @@ public class PackageManagerService implements PackageSender, TestUtilityService mDirtyUsers.remove(userId); } mUserNeedsBadging.delete(userId); - mPermissionManager.onUserRemoved(userId); + mDeletePackageHelper.removeUnusedPackagesLPw(userManager, userId); mSettings.removeUserLPw(userId); mPendingBroadcasts.remove(userId); - mDeletePackageHelper.removeUnusedPackagesLPw(userManager, userId); mAppsFilter.onUserDeleted(snapshotComputer(), userId); + mPermissionManager.onUserRemoved(userId); } mInstantAppRegistry.onUserRemoved(userId); mPackageMonitorCallbackHelper.onUserRemoved(userId); @@ -4608,6 +4610,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService }); // Send UNSTOPPED broadcast if necessary if (wasStopped && Flags.stayStopped()) { + Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "unstoppedBroadcast"); final PackageManagerInternal pmi = mInjector.getLocalService(PackageManagerInternal.class); final int [] userIds = resolveUserIds(userId); @@ -4627,6 +4630,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService mPackageMonitorCallbackHelper.notifyPackageMonitor(Intent.ACTION_PACKAGE_UNSTOPPED, packageName, extras, userIds, null /* instantUserIds */, broadcastAllowList, mHandler, null /* filterExtras */); + Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } } } diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java index cd3416348153..85316920f363 100644 --- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java +++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java @@ -30,6 +30,7 @@ import static com.android.server.pm.PackageManagerService.COMPRESSED_EXTENSION; import static com.android.server.pm.PackageManagerService.DEBUG_COMPRESSION; import static com.android.server.pm.PackageManagerService.DEBUG_INTENT_MATCHING; import static com.android.server.pm.PackageManagerService.DEBUG_PREFERRED; +import static com.android.server.pm.PackageManagerService.DEFAULT_FILE_ACCESS_MODE; import static com.android.server.pm.PackageManagerService.RANDOM_CODEPATH_PREFIX; import static com.android.server.pm.PackageManagerService.RANDOM_DIR_PREFIX; import static com.android.server.pm.PackageManagerService.SHELL_PACKAGE_NAME; @@ -69,6 +70,7 @@ import android.os.Debug; import android.os.Environment; import android.os.FileUtils; import android.os.Process; +import android.os.SELinux; import android.os.SystemProperties; import android.os.UserHandle; import android.os.incremental.IncrementalManager; @@ -129,10 +131,12 @@ import java.security.SecureRandom; import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateException; import java.text.SimpleDateFormat; +import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.List; import java.util.Objects; +import java.util.Set; import java.util.function.Function; import java.util.function.Predicate; import java.util.zip.GZIPInputStream; @@ -853,7 +857,7 @@ public class PackageManagerServiceUtils { FileUtils.copy(fileIn, outputStream); // Flush anything in buffer before chmod, because any writes after chmod will fail. outputStream.flush(); - Os.fchmod(outputStream.getFD(), 0644); + Os.fchmod(outputStream.getFD(), DEFAULT_FILE_ACCESS_MODE); atomicFile.finishWrite(outputStream); return PackageManager.INSTALL_SUCCEEDED; } catch (IOException e) { @@ -1081,8 +1085,8 @@ public class PackageManagerServiceUtils { final File targetFile = new File(targetDir, targetName); final FileDescriptor targetFd = Os.open(targetFile.getAbsolutePath(), - O_RDWR | O_CREAT, 0644); - Os.chmod(targetFile.getAbsolutePath(), 0644); + O_RDWR | O_CREAT, DEFAULT_FILE_ACCESS_MODE); + Os.chmod(targetFile.getAbsolutePath(), DEFAULT_FILE_ACCESS_MODE); FileInputStream source = null; try { source = new FileInputStream(sourcePath); @@ -1552,4 +1556,72 @@ public class PackageManagerServiceUtils { public static boolean isInstalledByAdb(String initiatingPackageName) { return initiatingPackageName == null || SHELL_PACKAGE_NAME.equals(initiatingPackageName); } + + public static void linkSplitsToOldDirs(@NonNull Installer installer, + @NonNull String packageName, + @NonNull File newPath, + @Nullable Set<File> oldPaths) { + if (oldPaths == null || oldPaths.isEmpty()) { + return; + } + if (IncrementalManager.isIncrementalPath(newPath.getPath())) { + //TODO(b/291212866): handle incremental installs + return; + } + final File[] filesInNewPath = newPath.listFiles(); + if (filesInNewPath == null || filesInNewPath.length == 0) { + return; + } + final List<String> splitApkNames = new ArrayList<String>(); + for (int i = 0; i < filesInNewPath.length; i++) { + if (!filesInNewPath[i].isDirectory() && filesInNewPath[i].toString().endsWith(".apk")) { + splitApkNames.add(filesInNewPath[i].getName()); + } + } + final int numSplits = splitApkNames.size(); + if (numSplits == 0) { + return; + } + for (File oldPath : oldPaths) { + if (!oldPath.exists()) { + continue; + } + for (int i = 0; i < numSplits; i++) { + final String splitApkName = splitApkNames.get(i); + final File linkedSplit = new File(oldPath, splitApkName); + if (linkedSplit.exists()) { + if (DEBUG) { + Slog.d(PackageManagerService.TAG, "Skipping existing linked split <" + + linkedSplit + ">"); + } + continue; + } + final File sourceSplit = new File(newPath, splitApkName); + try { + installer.linkFile(packageName, splitApkName, + newPath.getAbsolutePath(), oldPath.getAbsolutePath()); + if (DEBUG) { + Slog.d(PackageManagerService.TAG, "Linked <" + + sourceSplit + "> to <" + linkedSplit + ">"); + } + } catch (Installer.InstallerException e) { + Slog.w(PackageManagerService.TAG, "Failed to link split <" + + sourceSplit + " > to <" + linkedSplit + ">", e); + continue; + } + try { + Os.chmod(linkedSplit.getAbsolutePath(), DEFAULT_FILE_ACCESS_MODE); + } catch (ErrnoException e) { + Slog.w(PackageManagerService.TAG, "Failed to set mode for linked split <" + + linkedSplit + ">", e); + continue; + } + if (!SELinux.restorecon(linkedSplit)) { + Slog.w(PackageManagerService.TAG, "Failed to restorecon for linked split <" + + linkedSplit + ">"); + } + } + } + //TODO(b/291212866): support native libs + } } diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java index ca00c84da724..5c9c8c6d249a 100644 --- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java +++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java @@ -28,6 +28,7 @@ import static android.content.pm.PackageManager.RESTRICTION_HIDE_NOTIFICATIONS; import static android.content.pm.PackageManager.RESTRICTION_NONE; import static com.android.server.LocalManagerRegistry.ManagerNotFoundException; +import static com.android.server.pm.PackageManagerService.DEFAULT_FILE_ACCESS_MODE; import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME; import android.accounts.IAccountManager; @@ -297,6 +298,8 @@ class PackageManagerShellCommand extends ShellCommand { return runSetHiddenSetting(true); case "unhide": return runSetHiddenSetting(false); + case "unstop": + return runSetStoppedState(false); case "suspend": return runSuspend(true, 0); case "suspend-quarantine": @@ -2347,7 +2350,7 @@ class PackageManagerShellCommand extends ShellCommand { Streams.copy(inStream, outStream); } // Give read permissions to the other group. - Os.chmod(outputProfilePath, /*mode*/ 0644 ); + Os.chmod(outputProfilePath, /*mode*/ DEFAULT_FILE_ACCESS_MODE); } catch (IOException | ErrnoException e) { pw.println("Error when reading the profile fd: " + e.getMessage()); e.printStackTrace(pw); @@ -2662,6 +2665,26 @@ class PackageManagerShellCommand extends ShellCommand { return 0; } + private int runSetStoppedState(boolean state) throws RemoteException { + int userId = UserHandle.USER_SYSTEM; + String option = getNextOption(); + if (option != null && option.equals("--user")) { + userId = UserHandle.parseUserArg(getNextArgRequired()); + } + + String pkg = getNextArg(); + if (pkg == null) { + getErrPrintWriter().println("Error: no package specified"); + return 1; + } + final int translatedUserId = + translateUserId(userId, UserHandle.USER_NULL, "runSetStoppedState"); + mInterface.setPackageStoppedState(pkg, state, translatedUserId); + getOutPrintWriter().println("Package " + pkg + " new stopped state: " + + mInterface.isPackageStoppedForUser(pkg, translatedUserId)); + return 0; + } + private int runSetDistractingRestriction() { final PrintWriter pw = getOutPrintWriter(); int userId = UserHandle.USER_SYSTEM; @@ -3694,7 +3717,19 @@ class PackageManagerShellCommand extends ShellCommand { // remember to set it themselves. params.installerPackageName = "com.android.shell"; } - sessionParams.installFlags |= PackageManager.INSTALL_ENABLE_ROLLBACK; + int rollbackStrategy = PackageManager.ROLLBACK_DATA_POLICY_RESTORE; + try { + rollbackStrategy = Integer.parseInt(peekNextArg()); + if (rollbackStrategy < PackageManager.ROLLBACK_DATA_POLICY_RESTORE + || rollbackStrategy > PackageManager.ROLLBACK_DATA_POLICY_RETAIN) { + throw new IllegalArgumentException( + rollbackStrategy + " is not a valid rollback data policy."); + } + getNextArg(); // pop the argument + } catch (NumberFormatException e) { + // not followed by a number assume ROLLBACK_DATA_POLICY_RESTORE. + } + sessionParams.setEnableRollback(true, rollbackStrategy); break; case "--staged-ready-timeout": params.stagedReadyTimeoutMs = Long.parseLong(getNextArgRequired()); @@ -3729,6 +3764,11 @@ class PackageManagerShellCommand extends ShellCommand { } else if (staged) { sessionParams.setStaged(); } + if ((sessionParams.installFlags & PackageManager.INSTALL_APEX) != 0 + && (sessionParams.installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0 + && sessionParams.rollbackDataPolicy == PackageManager.ROLLBACK_DATA_POLICY_WIPE) { + throw new IllegalArgumentException("Data policy 'wipe' is not supported for apex."); + } return params; } @@ -4807,7 +4847,7 @@ class PackageManagerShellCommand extends ShellCommand { pw.println(" [--install-reason 0/1/2/3/4] [--originating-uri URI]"); pw.println(" [--referrer URI] [--abi ABI_NAME] [--force-sdk]"); pw.println(" [--preload] [--instant] [--full] [--dont-kill]"); - pw.println(" [--enable-rollback]"); + pw.println(" [--enable-rollback [0/1/2]]"); pw.println(" [--force-uuid internal|UUID] [--pkg PACKAGE] [-S BYTES]"); pw.println(" [--apex] [--non-staged] [--force-non-staged]"); pw.println(" [--staged-ready-timeout TIMEOUT] [--ignore-dexopt-profile]"); @@ -4831,6 +4871,8 @@ class PackageManagerShellCommand extends ShellCommand { pw.println(" --abi: override the default ABI of the platform"); pw.println(" --instant: cause the app to be installed as an ephemeral install app"); pw.println(" --full: cause the app to be installed as a non-ephemeral full app"); + pw.println(" --enable-rollback: enable rollbacks for the upgrade."); + pw.println(" 0=restore (default), 1=wipe, 2=retain"); pw.println(" --install-location: force the install location:"); pw.println(" 0=auto, 1=internal only, 2=prefer external"); pw.println(" --install-reason: indicates why the app is being installed:"); @@ -4934,6 +4976,8 @@ class PackageManagerShellCommand extends ShellCommand { pw.println(" hide [--user USER_ID] PACKAGE_OR_COMPONENT"); pw.println(" unhide [--user USER_ID] PACKAGE_OR_COMPONENT"); pw.println(""); + pw.println(" unstop [--user USER_ID] PACKAGE"); + pw.println(""); pw.println(" suspend [--user USER_ID] PACKAGE [PACKAGE...]"); pw.println(" Suspends the specified package(s) (as user)."); pw.println(""); diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java index 45fc49a2e855..74c482b47745 100644 --- a/services/core/java/com/android/server/pm/PackageSetting.java +++ b/services/core/java/com/android/server/pm/PackageSetting.java @@ -1112,6 +1112,29 @@ public class PackageSetting extends SettingBase implements PackageStateInternal return changed; } + void restoreComponentSettings(int userId) { + PackageUserStateImpl state = modifyUserStateComponents(userId, true, true); + WatchedArraySet<String> enabledComponents = state.getEnabledComponentsNoCopy(); + WatchedArraySet<String> disabledComponents = state.getDisabledComponentsNoCopy(); + + boolean changed = false; + for (int i = enabledComponents.size() - 1; i >= 0; i--) { + if (!AndroidPackageUtils.hasComponentClassName(pkg, enabledComponents.valueAt(i))) { + enabledComponents.removeAt(i); + changed = true; + } + } + for (int i = disabledComponents.size() - 1; i >= 0; i--) { + if (!AndroidPackageUtils.hasComponentClassName(pkg, disabledComponents.valueAt(i))) { + disabledComponents.removeAt(i); + changed = true; + } + } + if (changed) { + onChanged(); + } + } + int getCurrentEnabledStateLPr(String componentName, int userId) { PackageUserStateInternal state = readUserState(userId); if (state.getEnabledComponentsNoCopy() != null diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index c94111c31ef4..a6598d602d01 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -712,19 +712,24 @@ public class UserManagerService extends IUserManager.Stub { boolean isAutoLockOnDeviceLockSelected = autoLockPreference == Settings.Secure.PRIVATE_SPACE_AUTO_LOCK_ON_DEVICE_LOCK; if (isKeyguardLocked && isAutoLockOnDeviceLockSelected) { - int privateProfileUserId = getPrivateProfileUserId(); - if (privateProfileUserId != UserHandle.USER_NULL) { - Slog.i(LOG_TAG, "Auto-locking private space with user-id " - + privateProfileUserId); - setQuietModeEnabledAsync(privateProfileUserId, - /* enableQuietMode */true, /* target */ null, - mContext.getPackageName()); - } + autoLockPrivateSpace(); } } } @VisibleForTesting + void autoLockPrivateSpace() { + int privateProfileUserId = getPrivateProfileUserId(); + if (privateProfileUserId != UserHandle.USER_NULL) { + Slog.i(LOG_TAG, "Auto-locking private space with user-id " + + privateProfileUserId); + setQuietModeEnabledAsync(privateProfileUserId, + /* enableQuietMode */true, /* target */ null, + mContext.getPackageName()); + } + } + + @VisibleForTesting void setQuietModeEnabledAsync(@UserIdInt int userId, boolean enableQuietMode, IntentSender target, @Nullable String callingPackage) { if (android.multiuser.Flags.moveQuietModeOperationsToSeparateThread()) { @@ -1036,9 +1041,18 @@ public class UserManagerService extends IUserManager.Stub { } } + if (isAutoLockingPrivateSpaceOnRestartsEnabled()) { + autoLockPrivateSpace(); + } + markEphemeralUsersForRemoval(); } + private boolean isAutoLockingPrivateSpaceOnRestartsEnabled() { + return android.os.Flags.allowPrivateProfile() + && android.multiuser.Flags.enablePrivateSpaceAutolockOnRestarts(); + } + /** * This method retrieves the {@link UserManagerInternal} only for the purpose of * PackageManagerService construction. diff --git a/services/core/java/com/android/server/pm/permission/PermissionAllowlist.java b/services/core/java/com/android/server/pm/permission/PermissionAllowlist.java index 3efac81d44e3..d138606369b9 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionAllowlist.java +++ b/services/core/java/com/android/server/pm/permission/PermissionAllowlist.java @@ -26,6 +26,7 @@ import android.util.ArrayMap; public final class PermissionAllowlist { @NonNull private final ArrayMap<String, ArrayMap<String, Boolean>> mOemAppAllowlist = new ArrayMap<>(); + @NonNull private final ArrayMap<String, ArrayMap<String, Boolean>> mPrivilegedAppAllowlist = new ArrayMap<>(); @@ -43,6 +44,19 @@ public final class PermissionAllowlist { mApexPrivilegedAppAllowlists = new ArrayMap<>(); @NonNull + private final ArrayMap<String, ArrayMap<String, Boolean>> mSignatureAppAllowlist = + new ArrayMap<>(); + @NonNull + private final ArrayMap<String, ArrayMap<String, Boolean>> mVendorSignatureAppAllowlist = + new ArrayMap<>(); + @NonNull + private final ArrayMap<String, ArrayMap<String, Boolean>> mProductSignatureAppAllowlist = + new ArrayMap<>(); + @NonNull + private final ArrayMap<String, ArrayMap<String, Boolean>> mSystemExtSignatureAppAllowlist = + new ArrayMap<>(); + + @NonNull public ArrayMap<String, ArrayMap<String, Boolean>> getOemAppAllowlist() { return mOemAppAllowlist; } @@ -73,6 +87,26 @@ public final class PermissionAllowlist { return mApexPrivilegedAppAllowlists; } + @NonNull + public ArrayMap<String, ArrayMap<String, Boolean>> getSignatureAppAllowlist() { + return mSignatureAppAllowlist; + } + + @NonNull + public ArrayMap<String, ArrayMap<String, Boolean>> getVendorSignatureAppAllowlist() { + return mVendorSignatureAppAllowlist; + } + + @NonNull + public ArrayMap<String, ArrayMap<String, Boolean>> getProductSignatureAppAllowlist() { + return mProductSignatureAppAllowlist; + } + + @NonNull + public ArrayMap<String, ArrayMap<String, Boolean>> getSystemExtSignatureAppAllowlist() { + return mSystemExtSignatureAppAllowlist; + } + @Nullable public Boolean getOemAppAllowlistState(@NonNull String packageName, @NonNull String permissionName) { @@ -137,4 +171,44 @@ public final class PermissionAllowlist { } return permissions.get(permissionName); } + + @Nullable + public Boolean getSignatureAppAllowlistState(@NonNull String packageName, + @NonNull String permissionName) { + ArrayMap<String, Boolean> permissions = mSignatureAppAllowlist.get(packageName); + if (permissions == null) { + return null; + } + return permissions.get(permissionName); + } + + @Nullable + public Boolean getVendorSignatureAppAllowlistState(@NonNull String packageName, + @NonNull String permissionName) { + ArrayMap<String, Boolean> permissions = mVendorSignatureAppAllowlist.get(packageName); + if (permissions == null) { + return null; + } + return permissions.get(permissionName); + } + + @Nullable + public Boolean getProductSignatureAppAllowlistState(@NonNull String packageName, + @NonNull String permissionName) { + ArrayMap<String, Boolean> permissions = mProductSignatureAppAllowlist.get(packageName); + if (permissions == null) { + return null; + } + return permissions.get(permissionName); + } + + @Nullable + public Boolean getSystemExtSignatureAppAllowlistState(@NonNull String packageName, + @NonNull String permissionName) { + ArrayMap<String, Boolean> permissions = mSystemExtSignatureAppAllowlist.get(packageName); + if (permissions == null) { + return null; + } + return permissions.get(permissionName); + } } diff --git a/services/core/java/com/android/server/pm/pkg/PackageStateInternal.java b/services/core/java/com/android/server/pm/pkg/PackageStateInternal.java index c73728393016..f7603b5cfb57 100644 --- a/services/core/java/com/android/server/pm/pkg/PackageStateInternal.java +++ b/services/core/java/com/android/server/pm/pkg/PackageStateInternal.java @@ -27,6 +27,8 @@ import com.android.server.pm.InstallSource; import com.android.server.pm.PackageKeySetData; import com.android.server.pm.permission.LegacyPermissionState; +import java.io.File; +import java.util.Set; import java.util.UUID; /** @@ -111,4 +113,7 @@ public interface PackageStateInternal extends PackageState { */ @Nullable String getAppMetadataFilePath(); + + @Nullable + Set<File> getOldPaths(); } diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index bf669fba82ce..0abf304c34ee 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -5634,7 +5634,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { Trace.asyncTraceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "screenTurningOn", 0 /* cookie */); updateScreenOffSleepToken(false /* acquire */, false /* isSwappingDisplay */); - mDefaultDisplayPolicy.screenTurnedOn(screenOnListener); + mDefaultDisplayPolicy.screenTurningOn(screenOnListener); mBootAnimationDismissable = false; synchronized (mLock) { @@ -5676,6 +5676,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { mKeyguardDelegate.onScreenTurnedOn(); } } + mDefaultDisplayPolicy.screenTurnedOn(); reportScreenStateToVrManager(true); } diff --git a/services/core/java/com/android/server/policy/role/RoleServicePlatformHelperImpl.java b/services/core/java/com/android/server/policy/role/RoleServicePlatformHelperImpl.java index 5e8b4de3894e..7808c4ed50a4 100644 --- a/services/core/java/com/android/server/policy/role/RoleServicePlatformHelperImpl.java +++ b/services/core/java/com/android/server/policy/role/RoleServicePlatformHelperImpl.java @@ -30,6 +30,7 @@ import android.content.pm.PackageManagerInternal; import android.content.pm.ResolveInfo; import android.content.pm.Signature; import android.os.Environment; +import android.permission.flags.Flags; import android.provider.Settings; import android.text.TextUtils; import android.util.ArrayMap; @@ -368,6 +369,7 @@ public class RoleServicePlatformHelperImpl implements RoleServicePlatformHelper dataOutputStream.writeUTF(profileOwner); dataOutputStream.writeInt(Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.DEVICE_DEMO_MODE, 0)); + dataOutputStream.writeBoolean(Flags.walletRoleEnabled()); dataOutputStream.flush(); } catch (IOException e) { // Never happens for MessageDigestOutputStream and DataOutputStream. diff --git a/services/core/java/com/android/server/policy/window_policy_flags.aconfig b/services/core/java/com/android/server/policy/window_policy_flags.aconfig index ed981e0aca74..2154a26acbaf 100644 --- a/services/core/java/com/android/server/policy/window_policy_flags.aconfig +++ b/services/core/java/com/android/server/policy/window_policy_flags.aconfig @@ -4,5 +4,5 @@ flag { name: "support_input_wakeup_delegate" namespace: "wear_frameworks" description: "Whether or not window policy allows injecting input wake-up delegate." - bug: "298055811" + bug: "319132073" }
\ No newline at end of file diff --git a/services/core/java/com/android/server/power/ShutdownThread.java b/services/core/java/com/android/server/power/ShutdownThread.java index 871e98bf4ab3..4bf8a78a1f16 100644 --- a/services/core/java/com/android/server/power/ShutdownThread.java +++ b/services/core/java/com/android/server/power/ShutdownThread.java @@ -319,6 +319,11 @@ public final class ShutdownThread extends Thread { pd.setMax(100); pd.setProgress(0); pd.setIndeterminate(false); + boolean showPercent = context.getResources().getBoolean( + com.android.internal.R.bool.config_showPercentageTextDuringRebootToUpdate); + if (!showPercent) { + pd.setProgressPercentFormat(null); + } pd.setProgressNumberFormat(null); pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); pd.setMessage(context.getText( @@ -911,4 +916,4 @@ public final class ShutdownThread extends Thread { com.android.internal.R.string.config_defaultShutdownVibrationFile); } } -}
\ No newline at end of file +} diff --git a/services/core/java/com/android/server/rollback/README.md b/services/core/java/com/android/server/rollback/README.md index 08800dada564..f6bcbd057307 100644 --- a/services/core/java/com/android/server/rollback/README.md +++ b/services/core/java/com/android/server/rollback/README.md @@ -187,13 +187,22 @@ executed. ### Installing an App with Rollback Enabled -The `adb install` command accepts the `--enable-rollback` flag to install an app +The `adb install` command accepts the `--enable-rollback [0/1/2]` flag to install an app with rollback enabled. For example: ``` $ adb install --enable-rollback FooV2.apk ``` +The default rollback data policy is `ROLLBACK_DATA_POLICY_RESTORE` (0). To use +a different `RollbackDataPolicy`, like `ROLLBACK_DATA_POLICY_RETAIN` (1) or +`ROLLBACK_DATA_POLICY_WIPE` (2), provide the int value after +`--enable-rollback`. For example: + +``` +$ adb install --enable-rollback 1 FooV2.apk +``` + ### Triggering Rollback Manually If rollback is available for an application, the pm command can be used to @@ -217,7 +226,7 @@ $ adb shell dumpsys rollback -state: committed -timestamp: 2019-04-23T14:57:35.944Z -packages: - com.android.tests.rollback.testapp.B 2 -> 1 + com.android.tests.rollback.testapp.B 2 -> 1 [0] -causePackages: -committedSessionId: 1845805640 649899517: @@ -225,7 +234,7 @@ $ adb shell dumpsys rollback -timestamp: 2019-04-23T12:55:21.342Z -stagedSessionId: 343374391 -packages: - com.android.tests.rollback.testapex 2 -> 1 + com.android.tests.rollback.testapex 2 -> 1 [0] -causePackages: -committedSessionId: 2096717281 ``` @@ -233,7 +242,8 @@ $ adb shell dumpsys rollback The example above shows two recently committed rollbacks. The update of com.android.tests.rollback.testapp.B from version 1 to version 2 was rolled back, and the update of com.android.tests.rollback.testapex from version 1 to -version 2 was rolled back. +version 2 was rolled back. For each package the value inside '[' and ']' +indicates the `RollbackDataPolicy` for the rollback back. The state is 'available' or 'committed'. The timestamp gives the time when the rollback was first made available. If a stagedSessionId is present, then the diff --git a/services/core/java/com/android/server/rollback/Rollback.java b/services/core/java/com/android/server/rollback/Rollback.java index a5b90f12a5cc..d1f91c89a04e 100644 --- a/services/core/java/com/android/server/rollback/Rollback.java +++ b/services/core/java/com/android/server/rollback/Rollback.java @@ -215,7 +215,8 @@ class Rollback { /* packages */ new ArrayList<>(), /* isStaged */ isStaged, /* causePackages */ new ArrayList<>(), - /* committedSessionId */ -1); + /* committedSessionId */ -1, + /* rollbackImpactLevel */ PackageManager.ROLLBACK_USER_IMPACT_LOW); mUserId = userId; mInstallerPackageName = installerPackageName; mBackupDir = backupDir; @@ -394,7 +395,8 @@ class Rollback { */ @WorkerThread boolean enableForPackage(String packageName, long newVersion, long installedVersion, - boolean isApex, String sourceDir, String[] splitSourceDirs, int rollbackDataPolicy) { + boolean isApex, String sourceDir, String[] splitSourceDirs, int rollbackDataPolicy, + @PackageManager.RollbackImpactLevel int rollbackImpactLevel) { assertInWorkerThread(); try { RollbackStore.backupPackageCodePath(this, packageName, sourceDir); @@ -415,6 +417,10 @@ class Rollback { isApex, false /* isApkInApex */, new ArrayList<>(), rollbackDataPolicy); info.getPackages().add(packageRollbackInfo); + + if (info.getRollbackImpactLevel() < rollbackImpactLevel) { + info.setRollbackImpactLevel(rollbackImpactLevel); + } return true; } @@ -961,7 +967,8 @@ class Rollback { for (PackageRollbackInfo pkg : info.getPackages()) { ipw.println(pkg.getPackageName() + " " + pkg.getVersionRolledBackFrom().getLongVersionCode() - + " -> " + pkg.getVersionRolledBackTo().getLongVersionCode()); + + " -> " + pkg.getVersionRolledBackTo().getLongVersionCode() + + " [" + pkg.getRollbackDataPolicy() + "]"); } ipw.decreaseIndent(); if (isCommitted()) { diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java index 13f114138261..359678b15213 100644 --- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java +++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java @@ -954,7 +954,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub implements Rollba ApplicationInfo appInfo = pkgInfo.applicationInfo; return rollback.enableForPackage(packageName, newPackage.getVersionCode(), pkgInfo.getLongVersionCode(), isApex, appInfo.sourceDir, - appInfo.splitSourceDirs, rollbackDataPolicy); + appInfo.splitSourceDirs, rollbackDataPolicy, session.rollbackImpactLevel); } @ExtThread diff --git a/services/core/java/com/android/server/rollback/RollbackStore.java b/services/core/java/com/android/server/rollback/RollbackStore.java index 0af137faf5b4..14539d544bf9 100644 --- a/services/core/java/com/android/server/rollback/RollbackStore.java +++ b/services/core/java/com/android/server/rollback/RollbackStore.java @@ -193,16 +193,27 @@ class RollbackStore { json.put("isStaged", rollback.isStaged()); json.put("causePackages", versionedPackagesToJson(rollback.getCausePackages())); json.put("committedSessionId", rollback.getCommittedSessionId()); + if (Flags.recoverabilityDetection()) { + json.put("rollbackImpactLevel", rollback.getRollbackImpactLevel()); + } return json; } private static RollbackInfo rollbackInfoFromJson(JSONObject json) throws JSONException { - return new RollbackInfo( + RollbackInfo rollbackInfo = new RollbackInfo( json.getInt("rollbackId"), packageRollbackInfosFromJson(json.getJSONArray("packages")), json.getBoolean("isStaged"), versionedPackagesFromJson(json.getJSONArray("causePackages")), json.getInt("committedSessionId")); + + if (Flags.recoverabilityDetection()) { + // to make it backward compatible. + rollbackInfo.setRollbackImpactLevel(json.optInt("rollbackImpactLevel", + PackageManager.ROLLBACK_USER_IMPACT_LOW)); + } + + return rollbackInfo; } /** diff --git a/services/core/java/com/android/server/tv/TvInputHardwareManager.java b/services/core/java/com/android/server/tv/TvInputHardwareManager.java index b384725711c4..92b57645b9a3 100755 --- a/services/core/java/com/android/server/tv/TvInputHardwareManager.java +++ b/services/core/java/com/android/server/tv/TvInputHardwareManager.java @@ -309,6 +309,24 @@ class TvInputHardwareManager implements TvInputHal.Callback { } } + public SparseArray<String> getHardwareInputIdMap() { + synchronized (mLock) { + return mHardwareInputIdMap.clone(); + } + } + + public SparseArray<String> getHdmiInputIdMap() { + synchronized (mLock) { + return mHdmiInputIdMap.clone(); + } + } + + public Map<String, TvInputInfo> getInputMap() { + synchronized (mLock) { + return Collections.unmodifiableMap(mInputMap); + } + } + public Map<String, List<String>> getHdmiParentInputMap() { synchronized (mLock) { return Collections.unmodifiableMap(mHdmiParentInputMap); diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java index 73fc8e9cfbc4..e434df7836c4 100644 --- a/services/core/java/com/android/server/tv/TvInputManagerService.java +++ b/services/core/java/com/android/server/tv/TvInputManagerService.java @@ -135,6 +135,7 @@ public final class TvInputManagerService extends SystemService { private static final int APP_TAG_SELF = TunedInfo.APP_TAG_SELF; private static final String PERMISSION_ACCESS_WATCHED_PROGRAMS = "com.android.providers.tv.permission.ACCESS_WATCHED_PROGRAMS"; + private static final long UPDATE_HARDWARE_TIS_BINDING_DELAY_IN_MILLIS = 10 * 1000; // 10 seconds // There are two different formats of DVB frontend devices. One is /dev/dvb%d.frontend%d, // another one is /dev/dvb/adapter%d/frontend%d. Followings are the patterns for selecting the @@ -174,7 +175,7 @@ public final class TvInputManagerService extends SystemService { @GuardedBy("mLock") private final Map<String, SessionState> mSessionIdToSessionStateMap = new HashMap<>(); - private final WatchLogHandler mWatchLogHandler; + private final MessageHandler mMessageHandler; private final ActivityManager mActivityManager; @@ -187,8 +188,8 @@ public final class TvInputManagerService extends SystemService { super(context); mContext = context; - mWatchLogHandler = new WatchLogHandler(mContext.getContentResolver(), - IoThread.get().getLooper()); + mMessageHandler = + new MessageHandler(mContext.getContentResolver(), IoThread.get().getLooper()); mTvInputHardwareManager = new TvInputHardwareManager(context, new HardwareListener()); mActivityManager = @@ -372,10 +373,10 @@ public final class TvInputManagerService extends SystemService { // service to populate the hardware list. serviceState = new ServiceState(component, userId); userState.serviceStateMap.put(component, serviceState); + updateServiceConnectionLocked(component, userId); } else { inputList.addAll(serviceState.hardwareInputMap.values()); } - updateServiceConnectionLocked(component, userId); } else { try { TvInputInfo info = new TvInputInfo.Builder(mContext, ri).build(); @@ -510,6 +511,7 @@ public final class TvInputManagerService extends SystemService { } } + @GuardedBy("mLock") private void startProfileLocked(int userId) { mRunningProfiles.add(userId); buildTvInputListLocked(userId, null); @@ -538,8 +540,10 @@ public final class TvInputManagerService extends SystemService { mCurrentUserId = userId; buildTvInputListLocked(userId, null); buildTvContentRatingSystemListLocked(userId); - mWatchLogHandler.obtainMessage(WatchLogHandler.MSG_SWITCH_CONTENT_RESOLVER, - getContentResolverForUser(userId)).sendToTarget(); + mMessageHandler + .obtainMessage(MessageHandler.MSG_SWITCH_CONTENT_RESOLVER, + getContentResolverForUser(userId)) + .sendToTarget(); } } @@ -593,7 +597,7 @@ public final class TvInputManagerService extends SystemService { Slog.e(TAG, "error in unregisterCallback", e); } } - mContext.unbindService(serviceState.connection); + unbindService(serviceState); it.remove(); } } @@ -661,7 +665,7 @@ public final class TvInputManagerService extends SystemService { Slog.e(TAG, "error in unregisterCallback", e); } } - mContext.unbindService(serviceState.connection); + unbindService(serviceState); } } userState.serviceStateMap.clear(); @@ -774,7 +778,8 @@ public final class TvInputManagerService extends SystemService { boolean shouldBind; if (userId == mCurrentUserId || mRunningProfiles.contains(userId)) { - shouldBind = !serviceState.sessionTokens.isEmpty() || serviceState.isHardware; + shouldBind = !serviceState.sessionTokens.isEmpty() + || (serviceState.isHardware && serviceState.neverConnected); } else { // For a non-current user, // if sessionTokens is not empty, it contains recording sessions only @@ -783,31 +788,14 @@ public final class TvInputManagerService extends SystemService { shouldBind = !serviceState.sessionTokens.isEmpty(); } - if (serviceState.service == null && shouldBind) { - // This means that the service is not yet connected but its state indicates that we - // have pending requests. Then, connect the service. - if (serviceState.bound) { - // We have already bound to the service so we don't try to bind again until after we - // unbind later on. - return; - } - if (DEBUG) { - Slog.d(TAG, "bindServiceAsUser(service=" + component + ", userId=" + userId + ")"); - } - - Intent i = new Intent(TvInputService.SERVICE_INTERFACE).setComponent(component); - serviceState.bound = mContext.bindServiceAsUser( - i, serviceState.connection, - Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE, - new UserHandle(userId)); - } else if (serviceState.service != null && !shouldBind) { - // This means that the service is already connected but its state indicates that we have - // nothing to do with it. Then, disconnect the service. - if (DEBUG) { - Slog.d(TAG, "unbindService(service=" + component + ")"); + // only bind/unbind when necessary. + if (shouldBind && !serviceState.bound) { + bindService(serviceState, userId); + } else if (!shouldBind && serviceState.bound) { + unbindService(serviceState); + if (!serviceState.isHardware) { + userState.serviceStateMap.remove(component); } - mContext.unbindService(serviceState.connection); - userState.serviceStateMap.remove(component); } } @@ -829,7 +817,11 @@ public final class TvInputManagerService extends SystemService { sendSessionTokenToClientLocked(sessionState.client, sessionState.inputId, null, null, sessionState.seq); } - updateServiceConnectionLocked(serviceState.component, userId); + if (!serviceState.isHardware) { + updateServiceConnectionLocked(serviceState.component, userId); + } else { + updateHardwareServiceConnectionDelayed(userId); + } } @GuardedBy("mLock") @@ -948,13 +940,17 @@ public final class TvInputManagerService extends SystemService { if (serviceState != null) { serviceState.sessionTokens.remove(sessionToken); } - updateServiceConnectionLocked(sessionState.componentName, userId); + if (!serviceState.isHardware) { + updateServiceConnectionLocked(sessionState.componentName, userId); + } else { + updateHardwareServiceConnectionDelayed(userId); + } // Log the end of watch. SomeArgs args = SomeArgs.obtain(); args.arg1 = sessionToken; args.arg2 = System.currentTimeMillis(); - mWatchLogHandler.obtainMessage(WatchLogHandler.MSG_LOG_WATCH_END, args).sendToTarget(); + mMessageHandler.obtainMessage(MessageHandler.MSG_LOG_WATCH_END, args).sendToTarget(); } @GuardedBy("mLock") @@ -1153,8 +1149,7 @@ public final class TvInputManagerService extends SystemService { ServiceState serviceState = userState.serviceStateMap.get(inputState.info.getComponent()); int oldState = inputState.state; inputState.state = state; - if (serviceState != null && serviceState.service == null - && (!serviceState.sessionTokens.isEmpty() || serviceState.isHardware)) { + if (serviceState != null && serviceState.reconnecting) { // We don't notify state change while reconnecting. It should remain disconnected. return; } @@ -1881,7 +1876,7 @@ public final class TvInputManagerService extends SystemService { args.arg3 = ContentUris.parseId(channelUri); args.arg4 = params; args.arg5 = sessionToken; - mWatchLogHandler.obtainMessage(WatchLogHandler.MSG_LOG_WATCH_START, args) + mMessageHandler.obtainMessage(MessageHandler.MSG_LOG_WATCH_START, args) .sendToTarget(); } catch (RemoteException | SessionNotFoundException e) { Slog.e(TAG, "error in tune", e); @@ -3327,16 +3322,21 @@ public final class TvInputManagerService extends SystemService { private final ComponentName component; private final boolean isHardware; private final Map<String, TvInputInfo> hardwareInputMap = new HashMap<>(); + private final List<TvInputHardwareInfo> hardwareDeviceRemovedBuffer = new ArrayList<>(); + private final List<HdmiDeviceInfo> hdmiDeviceRemovedBuffer = new ArrayList<>(); + private final List<HdmiDeviceInfo> hdmiDeviceUpdatedBuffer = new ArrayList<>(); private ITvInputService service; private ServiceCallback callback; private boolean bound; private boolean reconnecting; + private boolean neverConnected; private ServiceState(ComponentName component, int userId) { this.component = component; this.connection = new InputServiceConnection(component, userId); this.isHardware = hasHardwarePermission(mContext.getPackageManager(), component); + this.neverConnected = true; } } @@ -3449,6 +3449,97 @@ public final class TvInputManagerService extends SystemService { } } + @GuardedBy("mLock") + private void bindService(ServiceState serviceState, int userId) { + if (serviceState.bound) { + // We have already bound to the service so we don't try to bind again until after we + // unbind later on. + // For hardware services, call updateHardwareServiceConnectionDelayed() to delay the + // possible unbinding. + if (serviceState.isHardware) { + updateHardwareServiceConnectionDelayed(userId); + } + return; + } + if (DEBUG) { + Slog.d(TAG, + "bindServiceAsUser(service=" + serviceState.component + ", userId=" + userId + + ")"); + } + Intent i = + new Intent(TvInputService.SERVICE_INTERFACE).setComponent(serviceState.component); + serviceState.bound = mContext.bindServiceAsUser(i, serviceState.connection, + Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE, + new UserHandle(userId)); + if (!serviceState.bound) { + Slog.e(TAG, "failed to bind " + serviceState.component + " for userId " + userId); + mContext.unbindService(serviceState.connection); + } + } + + @GuardedBy("mLock") + private void unbindService(ServiceState serviceState) { + if (!serviceState.bound) { + return; + } + if (DEBUG) { + Slog.d(TAG, "unbindService(service=" + serviceState.component + ")"); + } + mContext.unbindService(serviceState.connection); + serviceState.bound = false; + serviceState.service = null; + serviceState.callback = null; + } + + @GuardedBy("mLock") + private void updateHardwareTvInputServiceBindingLocked(int userId) { + PackageManager pm = mContext.getPackageManager(); + List<ResolveInfo> services = + pm.queryIntentServicesAsUser(new Intent(TvInputService.SERVICE_INTERFACE), + PackageManager.GET_SERVICES | PackageManager.GET_META_DATA, userId); + for (ResolveInfo ri : services) { + ServiceInfo si = ri.serviceInfo; + if (!android.Manifest.permission.BIND_TV_INPUT.equals(si.permission)) { + continue; + } + ComponentName component = new ComponentName(si.packageName, si.name); + if (hasHardwarePermission(pm, component)) { + updateServiceConnectionLocked(component, userId); + } + } + } + + private void updateHardwareServiceConnectionDelayed(int userId) { + mMessageHandler.removeMessages(MessageHandler.MSG_UPDATE_HARDWARE_TIS_BINDING); + SomeArgs args = SomeArgs.obtain(); + args.arg1 = userId; + Message msg = + mMessageHandler.obtainMessage(MessageHandler.MSG_UPDATE_HARDWARE_TIS_BINDING, args); + mMessageHandler.sendMessageDelayed(msg, UPDATE_HARDWARE_TIS_BINDING_DELAY_IN_MILLIS); + } + + @GuardedBy("mLock") + private void addHardwareInputLocked( + TvInputInfo inputInfo, ComponentName component, int userId) { + ServiceState serviceState = getServiceStateLocked(component, userId); + serviceState.hardwareInputMap.put(inputInfo.getId(), inputInfo); + buildTvInputListLocked(userId, null); + } + + @GuardedBy("mLock") + private void removeHardwareInputLocked(String inputId, int userId) { + if (!mTvInputHardwareManager.getInputMap().containsKey(inputId)) { + return; + } + ComponentName component = mTvInputHardwareManager.getInputMap().get(inputId).getComponent(); + ServiceState serviceState = getServiceStateLocked(component, userId); + boolean removed = serviceState.hardwareInputMap.remove(inputId) != null; + if (removed) { + buildTvInputListLocked(userId, null); + mTvInputHardwareManager.removeHardwareInput(inputId); + } + } + private final class InputServiceConnection implements ServiceConnection { private final ComponentName mComponent; private final int mUserId; @@ -3472,6 +3563,7 @@ public final class TvInputManagerService extends SystemService { } ServiceState serviceState = userState.serviceStateMap.get(mComponent); serviceState.service = ITvInputService.Stub.asInterface(service); + serviceState.neverConnected = false; // Register a callback, if we need to. if (serviceState.isHardware && serviceState.callback == null) { @@ -3483,19 +3575,6 @@ public final class TvInputManagerService extends SystemService { } } - List<IBinder> tokensToBeRemoved = new ArrayList<>(); - - // And create sessions, if any. - for (IBinder sessionToken : serviceState.sessionTokens) { - if (!createSessionInternalLocked(serviceState.service, sessionToken, mUserId)) { - tokensToBeRemoved.add(sessionToken); - } - } - - for (IBinder sessionToken : tokensToBeRemoved) { - removeSessionStateLocked(sessionToken, mUserId); - } - for (TvInputState inputState : userState.inputMap.values()) { if (inputState.info.getComponent().equals(component) && inputState.state != INPUT_STATE_CONNECTED) { @@ -3505,7 +3584,24 @@ public final class TvInputManagerService extends SystemService { } if (serviceState.isHardware) { - serviceState.hardwareInputMap.clear(); + for (TvInputHardwareInfo hardwareToBeRemoved : + serviceState.hardwareDeviceRemovedBuffer) { + try { + serviceState.service.notifyHardwareRemoved(hardwareToBeRemoved); + } catch (RemoteException e) { + Slog.e(TAG, "error in hardwareDeviceRemovedBuffer", e); + } + } + serviceState.hardwareDeviceRemovedBuffer.clear(); + for (HdmiDeviceInfo hdmiDeviceToBeRemoved : + serviceState.hdmiDeviceRemovedBuffer) { + try { + serviceState.service.notifyHdmiDeviceRemoved(hdmiDeviceToBeRemoved); + } catch (RemoteException e) { + Slog.e(TAG, "error in hdmiDeviceRemovedBuffer", e); + } + } + serviceState.hdmiDeviceRemovedBuffer.clear(); for (TvInputHardwareInfo hardware : mTvInputHardwareManager.getHardwareList()) { try { serviceState.service.notifyHardwareAdded(hardware); @@ -3520,6 +3616,32 @@ public final class TvInputManagerService extends SystemService { Slog.e(TAG, "error in notifyHdmiDeviceAdded", e); } } + for (HdmiDeviceInfo hdmiDeviceToBeUpdated : + serviceState.hdmiDeviceUpdatedBuffer) { + try { + serviceState.service.notifyHdmiDeviceUpdated(hdmiDeviceToBeUpdated); + } catch (RemoteException e) { + Slog.e(TAG, "error in hdmiDeviceUpdatedBuffer", e); + } + } + serviceState.hdmiDeviceUpdatedBuffer.clear(); + } + + List<IBinder> tokensToBeRemoved = new ArrayList<>(); + + // And create sessions, if any. + for (IBinder sessionToken : serviceState.sessionTokens) { + if (!createSessionInternalLocked(serviceState.service, sessionToken, mUserId)) { + tokensToBeRemoved.add(sessionToken); + } + } + + for (IBinder sessionToken : tokensToBeRemoved) { + removeSessionStateLocked(sessionToken, mUserId); + } + + if (serviceState.isHardware) { + updateHardwareServiceConnectionDelayed(mUserId); } } } @@ -3570,13 +3692,6 @@ public final class TvInputManagerService extends SystemService { } } - @GuardedBy("mLock") - private void addHardwareInputLocked(TvInputInfo inputInfo) { - ServiceState serviceState = getServiceStateLocked(mComponent, mUserId); - serviceState.hardwareInputMap.put(inputInfo.getId(), inputInfo); - buildTvInputListLocked(mUserId, null); - } - public void addHardwareInput(int deviceId, TvInputInfo inputInfo) { ensureHardwarePermission(); ensureValidInput(inputInfo); @@ -3587,8 +3702,11 @@ public final class TvInputManagerService extends SystemService { if (serviceState.hardwareInputMap.containsKey(inputInfo.getId())) { return; } + Slog.d("ServiceCallback", + "addHardwareInput: device id " + deviceId + ", " + + inputInfo.toString()); mTvInputHardwareManager.addHardwareInput(deviceId, inputInfo); - addHardwareInputLocked(inputInfo); + addHardwareInputLocked(inputInfo, mComponent, mUserId); } } finally { Binder.restoreCallingIdentity(identity); @@ -3606,7 +3724,7 @@ public final class TvInputManagerService extends SystemService { return; } mTvInputHardwareManager.addHdmiInput(id, inputInfo); - addHardwareInputLocked(inputInfo); + addHardwareInputLocked(inputInfo, mComponent, mUserId); if (mOnScreenInputId != null && mOnScreenSessionState != null) { if (TextUtils.equals(mOnScreenInputId, inputInfo.getParentId())) { // catch the use case when a CEC device is plugged in an HDMI port, @@ -3635,14 +3753,9 @@ public final class TvInputManagerService extends SystemService { final long identity = Binder.clearCallingIdentity(); try { synchronized (mLock) { - ServiceState serviceState = getServiceStateLocked(mComponent, mUserId); - boolean removed = serviceState.hardwareInputMap.remove(inputId) != null; - if (removed) { - buildTvInputListLocked(mUserId, null); - mTvInputHardwareManager.removeHardwareInput(inputId); - } else { - Slog.e(TAG, "failed to remove input " + inputId); - } + Slog.d("ServiceCallback", + "removeHardwareInput " + inputId + " by " + mComponent); + removeHardwareInputLocked(inputId, mUserId); } } finally { Binder.restoreCallingIdentity(identity); @@ -3860,6 +3973,23 @@ public final class TvInputManagerService extends SystemService { } @Override + public void onVideoFreezeUpdated(boolean isFrozen) { + synchronized (mLock) { + if (DEBUG) { + Slog.d(TAG, "onVideoFreezeUpdated(" + isFrozen + ")"); + } + if (mSessionState.session == null || mSessionState.client == null) { + return; + } + try { + mSessionState.client.onVideoFreezeUpdated(isFrozen, mSessionState.seq); + } catch (RemoteException e) { + Slog.e(TAG, "error in onVideoFreezeUpdated", e); + } + } + } + + @Override public void onContentAllowed() { synchronized (mLock) { if (DEBUG) { @@ -4209,11 +4339,12 @@ public final class TvInputManagerService extends SystemService { return loggedReason; } + @GuardedBy("mLock") private UserState getUserStateLocked(int userId) { return mUserStates.get(userId); } - private static final class WatchLogHandler extends Handler { + private final class MessageHandler extends Handler { // There are only two kinds of watch events that can happen on the system: // 1. The current TV input session is tuned to a new channel. // 2. The session is released for some reason. @@ -4225,10 +4356,11 @@ public final class TvInputManagerService extends SystemService { static final int MSG_LOG_WATCH_START = 1; static final int MSG_LOG_WATCH_END = 2; static final int MSG_SWITCH_CONTENT_RESOLVER = 3; + static final int MSG_UPDATE_HARDWARE_TIS_BINDING = 4; private ContentResolver mContentResolver; - WatchLogHandler(ContentResolver contentResolver, Looper looper) { + MessageHandler(ContentResolver contentResolver, Looper looper) { super(looper); mContentResolver = contentResolver; } @@ -4287,6 +4419,14 @@ public final class TvInputManagerService extends SystemService { mContentResolver = (ContentResolver) msg.obj; break; } + case MSG_UPDATE_HARDWARE_TIS_BINDING: + SomeArgs args = (SomeArgs) msg.obj; + int userId = (int) args.arg1; + synchronized (mLock) { + updateHardwareTvInputServiceBindingLocked(userId); + } + args.recycle(); + break; default: { Slog.w(TAG, "unhandled message code: " + msg.what); break; @@ -4342,29 +4482,46 @@ public final class TvInputManagerService extends SystemService { UserState userState = getOrCreateUserStateLocked(mCurrentUserId); // Broadcast the event to all hardware inputs. for (ServiceState serviceState : userState.serviceStateMap.values()) { - if (!serviceState.isHardware || serviceState.service == null) continue; + if (!serviceState.isHardware) { + continue; + } try { - serviceState.service.notifyHardwareAdded(info); + bindService(serviceState, mCurrentUserId); + if (serviceState.service != null) { + serviceState.service.notifyHardwareAdded(info); + } } catch (RemoteException e) { Slog.e(TAG, "error in notifyHardwareAdded", e); } } + updateHardwareServiceConnectionDelayed(mCurrentUserId); } } @Override public void onHardwareDeviceRemoved(TvInputHardwareInfo info) { synchronized (mLock) { + String relatedInputId = + mTvInputHardwareManager.getHardwareInputIdMap().get(info.getDeviceId()); + removeHardwareInputLocked(relatedInputId, mCurrentUserId); UserState userState = getOrCreateUserStateLocked(mCurrentUserId); // Broadcast the event to all hardware inputs. for (ServiceState serviceState : userState.serviceStateMap.values()) { - if (!serviceState.isHardware || serviceState.service == null) continue; + if (!serviceState.isHardware) { + continue; + } try { - serviceState.service.notifyHardwareRemoved(info); + bindService(serviceState, mCurrentUserId); + if (serviceState.service != null) { + serviceState.service.notifyHardwareRemoved(info); + } else { + serviceState.hardwareDeviceRemovedBuffer.add(info); + } } catch (RemoteException e) { Slog.e(TAG, "error in notifyHardwareRemoved", e); } } + updateHardwareServiceConnectionDelayed(mCurrentUserId); } } @@ -4374,29 +4531,46 @@ public final class TvInputManagerService extends SystemService { UserState userState = getOrCreateUserStateLocked(mCurrentUserId); // Broadcast the event to all hardware inputs. for (ServiceState serviceState : userState.serviceStateMap.values()) { - if (!serviceState.isHardware || serviceState.service == null) continue; + if (!serviceState.isHardware) { + continue; + } try { - serviceState.service.notifyHdmiDeviceAdded(deviceInfo); + bindService(serviceState, mCurrentUserId); + if (serviceState.service != null) { + serviceState.service.notifyHdmiDeviceAdded(deviceInfo); + } } catch (RemoteException e) { Slog.e(TAG, "error in notifyHdmiDeviceAdded", e); } } + updateHardwareServiceConnectionDelayed(mCurrentUserId); } } @Override public void onHdmiDeviceRemoved(HdmiDeviceInfo deviceInfo) { synchronized (mLock) { + String relatedInputId = + mTvInputHardwareManager.getHdmiInputIdMap().get(deviceInfo.getId()); + removeHardwareInputLocked(relatedInputId, mCurrentUserId); UserState userState = getOrCreateUserStateLocked(mCurrentUserId); // Broadcast the event to all hardware inputs. for (ServiceState serviceState : userState.serviceStateMap.values()) { - if (!serviceState.isHardware || serviceState.service == null) continue; + if (!serviceState.isHardware) { + continue; + } try { - serviceState.service.notifyHdmiDeviceRemoved(deviceInfo); + bindService(serviceState, mCurrentUserId); + if (serviceState.service != null) { + serviceState.service.notifyHdmiDeviceRemoved(deviceInfo); + } else { + serviceState.hdmiDeviceRemovedBuffer.add(deviceInfo); + } } catch (RemoteException e) { Slog.e(TAG, "error in notifyHdmiDeviceRemoved", e); } } + updateHardwareServiceConnectionDelayed(mCurrentUserId); } } @@ -4424,13 +4598,21 @@ public final class TvInputManagerService extends SystemService { UserState userState = getOrCreateUserStateLocked(mCurrentUserId); // Broadcast the event to all hardware inputs. for (ServiceState serviceState : userState.serviceStateMap.values()) { - if (!serviceState.isHardware || serviceState.service == null) continue; + if (!serviceState.isHardware) { + continue; + } try { - serviceState.service.notifyHdmiDeviceUpdated(deviceInfo); + bindService(serviceState, mCurrentUserId); + if (serviceState.service != null) { + serviceState.service.notifyHdmiDeviceUpdated(deviceInfo); + } else { + serviceState.hdmiDeviceUpdatedBuffer.add(deviceInfo); + } } catch (RemoteException e) { Slog.e(TAG, "error in notifyHdmiDeviceUpdated", e); } } + updateHardwareServiceConnectionDelayed(mCurrentUserId); } } 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 7ab075e2f3a7..9c60fbb6bb9a 100644 --- a/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java +++ b/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java @@ -1470,6 +1470,28 @@ public class TvInteractiveAppManagerService extends SystemService { } @Override + public void notifyVideoFreezeUpdated(IBinder sessionToken, boolean isFrozen, int userId) { + final int callingUid = Binder.getCallingUid(); + final int callingPid = Binder.getCallingPid(); + final int resolvedUserId = resolveCallingUserId(callingPid, callingUid, userId, + "notifyVideoFreezeUpdated"); + final long identity = Binder.clearCallingIdentity(); + try { + synchronized (mLock) { + try { + SessionState sessionState = getSessionStateLocked(sessionToken, callingUid, + resolvedUserId); + getSessionLocked(sessionState).notifyVideoFreezeUpdated(isFrozen); + } catch (RemoteException | SessionNotFoundException e) { + Slogf.e(TAG, "error in notifyVideoFreezeUpdated", e); + } + } + } finally { + Binder.restoreCallingIdentity(identity); + } + } + + @Override public void notifyContentAllowed(IBinder sessionToken, int userId) { final int callingUid = Binder.getCallingUid(); final int callingPid = Binder.getCallingPid(); @@ -1557,7 +1579,6 @@ public class TvInteractiveAppManagerService extends SystemService { } } - @Override public void notifyRecordingStarted(IBinder sessionToken, String recordingId, String requestId, int userId) { diff --git a/services/core/java/com/android/server/wallpaper/WallpaperCropper.java b/services/core/java/com/android/server/wallpaper/WallpaperCropper.java index 51acc8e01cda..8549957f46b8 100644 --- a/services/core/java/com/android/server/wallpaper/WallpaperCropper.java +++ b/services/core/java/com/android/server/wallpaper/WallpaperCropper.java @@ -410,9 +410,10 @@ public class WallpaperCropper { // adapt the entries in wallpaper.mCropHints for the actual display SparseArray<Rect> updatedCropHints = new SparseArray<>(); for (int i = 0; i < wallpaper.mCropHints.size(); i++) { - Rect defaultCrop = defaultDisplayCrops.valueAt(i); + int orientation = wallpaper.mCropHints.keyAt(i); + Rect defaultCrop = defaultDisplayCrops.get(orientation); if (defaultCrop != null) { - updatedCropHints.put(defaultDisplayCrops.keyAt(i), defaultCrop); + updatedCropHints.put(orientation, defaultCrop); } } wallpaper.mCropHints = updatedCropHints; diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 9b1f9c8441ad..036f7b6841c2 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -3965,20 +3965,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A return removedFromHistory; } - boolean safelyDestroy(String reason) { - if (isDestroyable()) { - if (DEBUG_SWITCH) { - final Task task = getTask(); - Slog.v(TAG_SWITCH, "Safely destroying " + this + " in state " + getState() - + " resumed=" + task.getTopResumedActivity() - + " pausing=" + task.getTopPausingActivity() - + " for reason " + reason); - } - return destroyImmediately(reason); - } - return false; - } - /** Note: call {@link #cleanUp(boolean, boolean)} before this method. */ void removeFromHistory(String reason) { finishActivityResults(Activity.RESULT_CANCELED, @@ -4047,10 +4033,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } } - boolean isFinishing() { - return finishing; - } - /** * This method is to only be called from the client via binder when the activity is destroyed * AND finished. @@ -7978,6 +7960,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A if (mLetterboxUiController.shouldIgnoreRequestedOrientation(requestedOrientation)) { return; } + final int originalRelaunchingCount = mPendingRelaunchCount; // This is necessary in order to avoid going into size compat mode when the orientation // change request comes from the app if (getRequestedConfigurationOrientation(false, requestedOrientation) @@ -7995,8 +7978,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // the request is handled at task level with letterbox. if (!getMergedOverrideConfiguration().equals( mLastReportedConfiguration.getMergedConfiguration())) { - ensureActivityConfiguration( - false /* ignoreVisibility */, true /* isRequestedOrientationChanged */); + ensureActivityConfiguration(false /* ignoreVisibility */); + if (mPendingRelaunchCount > originalRelaunchingCount) { + mLetterboxUiController.setRelaunchingAfterRequestedOrientationChanged(true); + } if (mTransitionController.inPlayingTransition(this)) { mTransitionController.mValidateActivityCompat.add(this); } @@ -9502,11 +9487,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A return ensureActivityConfiguration(false /* ignoreVisibility */); } - boolean ensureActivityConfiguration(boolean ignoreVisibility) { - return ensureActivityConfiguration(ignoreVisibility, - false /* isRequestedOrientationChanged */); - } - /** * Make sure the given activity matches the current configuration. Ensures the HistoryRecord * is updated with the correct configuration and all other bookkeeping is handled. @@ -9515,13 +9495,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A * (stopped state). This is useful for the case where we know the * activity will be visible soon and we want to ensure its configuration * before we make it visible. - * @param isRequestedOrientationChanged whether this is triggered in response to an app calling - * {@link android.app.Activity#setRequestedOrientation}. * @return False if the activity was relaunched and true if it wasn't relaunched because we * can't or the app handles the specific configuration that is changing. */ - boolean ensureActivityConfiguration(boolean ignoreVisibility, - boolean isRequestedOrientationChanged) { + boolean ensureActivityConfiguration(boolean ignoreVisibility) { final Task rootTask = getRootTask(); if (rootTask.mConfigWillChange) { ProtoLog.v(WM_DEBUG_CONFIGURATION, "Skipping config check " @@ -9658,9 +9635,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } else { mRelaunchReason = RELAUNCH_REASON_NONE; } - if (isRequestedOrientationChanged) { - mLetterboxUiController.setRelaunchingAfterRequestedOrientationChanged(true); - } if (mState == PAUSING) { // A little annoying: we are waiting for this activity to finish pausing. Let's not // do anything now, but just flag that it needs to be restarted when done pausing. diff --git a/services/core/java/com/android/server/wm/ActivitySecurityModelFeatureFlags.java b/services/core/java/com/android/server/wm/ActivitySecurityModelFeatureFlags.java index f1a2159d6dbe..db27f607c867 100644 --- a/services/core/java/com/android/server/wm/ActivitySecurityModelFeatureFlags.java +++ b/services/core/java/com/android/server/wm/ActivitySecurityModelFeatureFlags.java @@ -43,7 +43,7 @@ class ActivitySecurityModelFeatureFlags { static final String DOC_LINK = "go/android-asm"; /** Used to determine which version of the ASM logic was used in logs while we iterate */ - static final int ASM_VERSION = 8; + static final int ASM_VERSION = 9; private static final String NAMESPACE = NAMESPACE_WINDOW_MANAGER; private static final String KEY_ASM_PREFIX = "ActivitySecurity__"; diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java index f6d77ea33598..d6f52b89819e 100644 --- a/services/core/java/com/android/server/wm/ActivityStarter.java +++ b/services/core/java/com/android/server/wm/ActivityStarter.java @@ -2053,8 +2053,8 @@ class ActivityStarter { } if (!mSupervisor.getBackgroundActivityLaunchController().checkActivityAllowedToStart( - mSourceRecord, r, newTask, targetTask, mLaunchFlags, mBalCode, mCallingUid, - mRealCallingUid)) { + mSourceRecord, r, newTask, avoidMoveToFront(), targetTask, mLaunchFlags, mBalCode, + mCallingUid, mRealCallingUid)) { return START_ABORTED; } diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java index 5604b1a6aa39..ed556a55010e 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java @@ -796,4 +796,17 @@ public abstract class ActivityTaskManagerInternal { * @param token The activity token. */ public abstract int getDisplayId(IBinder token); + + /** + * Register a {@link CompatScaleProvider}. + */ + public abstract void registerCompatScaleProvider( + @CompatScaleProvider.CompatScaleModeOrderId int id, + @NonNull CompatScaleProvider provider); + + /** + * Unregister a {@link CompatScaleProvider}. + */ + public abstract void unregisterCompatScaleProvider( + @CompatScaleProvider.CompatScaleModeOrderId int id); } diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index 3959a5e54cbf..3397a3dd2290 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -7277,6 +7277,18 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { public void unregisterTaskStackListener(ITaskStackListener listener) { ActivityTaskManagerService.this.unregisterTaskStackListener(listener); } + + @Override + public void registerCompatScaleProvider(@CompatScaleProvider.CompatScaleModeOrderId int id, + @NonNull CompatScaleProvider provider) { + ActivityTaskManagerService.this.registerCompatScaleProvider(id, provider); + } + + @Override + public void unregisterCompatScaleProvider( + @CompatScaleProvider.CompatScaleModeOrderId int id) { + ActivityTaskManagerService.this.unregisterCompatScaleProvider(id); + } } static boolean isPip2ExperimentEnabled() { diff --git a/services/core/java/com/android/server/wm/BackNavigationController.java b/services/core/java/com/android/server/wm/BackNavigationController.java index 2bd49bfa6219..a4d15e07a3ed 100644 --- a/services/core/java/com/android/server/wm/BackNavigationController.java +++ b/services/core/java/com/android/server/wm/BackNavigationController.java @@ -19,6 +19,7 @@ package com.android.server.wm; import static android.app.ActivityTaskManager.INVALID_TASK_ID; import static android.view.RemoteAnimationTarget.MODE_CLOSING; import static android.view.RemoteAnimationTarget.MODE_OPENING; +import static android.view.View.FOCUS_FORWARD; import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; import static android.view.WindowManager.TRANSIT_CLOSE; import static android.view.WindowManager.TRANSIT_OLD_NONE; @@ -60,6 +61,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.policy.TransitionAnimation; import com.android.internal.protolog.common.ProtoLog; import com.android.server.wm.utils.InsetUtils; +import com.android.window.flags.Flags; import java.io.PrintWriter; import java.util.ArrayList; @@ -167,6 +169,24 @@ class BackNavigationController { return null; } + // Move focus to the adjacent embedded window if it is higher than this window + final TaskFragment taskFragment = window.getTaskFragment(); + final TaskFragment adjacentTaskFragment = + taskFragment != null ? taskFragment.getAdjacentTaskFragment() : null; + if (adjacentTaskFragment != null && taskFragment.isEmbedded() + && Flags.embeddedActivityBackNavFlag()) { + final WindowContainer parent = taskFragment.getParent(); + if (parent.mChildren.indexOf(taskFragment) < parent.mChildren.indexOf( + adjacentTaskFragment)) { + mWindowManagerService.moveFocusToAdjacentWindow(window, FOCUS_FORWARD); + window = wmService.getFocusedWindowLocked(); + if (window == null) { + Slog.e(TAG, "Adjacent window is null, returning null."); + return null; + } + } + } + // This is needed to bridge the old and new back behavior with recents. While in // Overview with live tile enabled, the previous app is technically focused but we // add an input consumer to capture all input that would otherwise go to the apps diff --git a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java index 0f36d8eafbe4..bcb4559d79e4 100644 --- a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java +++ b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java @@ -57,6 +57,7 @@ import android.content.ComponentName; import android.content.Intent; import android.content.pm.PackageManager; import android.os.Process; +import android.os.SystemClock; import android.os.UserHandle; import android.provider.DeviceConfig; import android.util.ArraySet; @@ -1042,8 +1043,9 @@ public class BackgroundActivityStartController { * create a new task or bring an existing one into the foreground */ boolean checkActivityAllowedToStart(@Nullable ActivityRecord sourceRecord, - @NonNull ActivityRecord targetRecord, boolean newTask, @NonNull Task targetTask, - int launchFlags, int balCode, int callingUid, int realCallingUid) { + @NonNull ActivityRecord targetRecord, boolean newTask, boolean avoidMoveTaskToFront, + @Nullable Task targetTask, int launchFlags, int balCode, int callingUid, + int realCallingUid) { // BAL Exception allowed in all cases if (balCode == BAL_ALLOW_ALLOWLISTED_UID) { return true; @@ -1067,14 +1069,36 @@ public class BackgroundActivityStartController { } if (balCode == BAL_ALLOW_GRACE_PERIOD) { + // Allow if launching into new task, and caller matches most recently finished activity if (taskToFront && mTopFinishedActivity != null && mTopFinishedActivity.mUid == callingUid) { return true; - } else if (!taskToFront) { - FinishedActivityEntry finishedEntry = - mTaskIdToFinishedActivity.get(targetTask.mTaskId); - if (finishedEntry != null && finishedEntry.mUid == callingUid) { - return true; + } + + // Launching into existing task - allow if matches most recently finished activity + // within the task. + // We can reach here multiple ways: + // 1. activity in fg fires intent (taskToFront = false, sourceRecord is available) + // 2. activity in bg fires intent (taskToFront = false, sourceRecord is available) + // 3. activity in bg fires intent with NEW_FLAG (taskToFront = true, + // avoidMoveTaskToFront = true, sourceRecord is available) + // 4. activity in bg fires PI (taskToFront = true, avoidMoveTaskToFront = true, + // sourceRecord is not available, targetTask may be available) + if (!taskToFront || avoidMoveTaskToFront) { + if (targetTask != null) { + FinishedActivityEntry finishedEntry = + mTaskIdToFinishedActivity.get(targetTask.mTaskId); + if (finishedEntry != null && finishedEntry.mUid == callingUid) { + return true; + } + } + + if (sourceRecord != null) { + FinishedActivityEntry finishedEntry = + mTaskIdToFinishedActivity.get(sourceRecord.getTask().mTaskId); + if (finishedEntry != null && finishedEntry.mUid == callingUid) { + return true; + } } } } @@ -1098,7 +1122,7 @@ public class BackgroundActivityStartController { bas = isTopActivityMatchingUidAbsentForAsm(taskToCheck, sourceRecord.getUid(), sourceRecord); } - } else if (!taskToFront) { + } else if (targetTask != null && (!taskToFront || avoidMoveTaskToFront)) { // We don't have a sourceRecord, and we're launching into an existing task. // Allow if callingUid is top of stack. bas = isTopActivityMatchingUidAbsentForAsm(targetTask, callingUid, @@ -1111,12 +1135,14 @@ public class BackgroundActivityStartController { // ASM rules have failed. Log why return logAsmFailureAndCheckFeatureEnabled(sourceRecord, callingUid, realCallingUid, - newTask, targetTask, targetRecord, balCode, launchFlags, bas, taskToFront); + newTask, avoidMoveTaskToFront, targetTask, targetRecord, balCode, launchFlags, + bas, taskToFront); } private boolean logAsmFailureAndCheckFeatureEnabled(ActivityRecord sourceRecord, int callingUid, - int realCallingUid, boolean newTask, Task targetTask, ActivityRecord targetRecord, - @BalCode int balCode, int launchFlags, BlockActivityStart bas, boolean taskToFront) { + int realCallingUid, boolean newTask, boolean avoidMoveTaskToFront, Task targetTask, + ActivityRecord targetRecord, @BalCode int balCode, int launchFlags, + BlockActivityStart bas, boolean taskToFront) { ActivityRecord targetTopActivity = targetTask == null ? null : targetTask.getActivity(ar -> !ar.finishing && !ar.isAlwaysOnTop()); @@ -1133,7 +1159,7 @@ public class BackgroundActivityStartController { String asmDebugInfo = getDebugInfoForActivitySecurity("Launch", sourceRecord, targetRecord, targetTask, targetTopActivity, realCallingUid, balCode, - blockActivityStartAndFeatureEnabled, taskToFront); + blockActivityStartAndFeatureEnabled, taskToFront, avoidMoveTaskToFront); FrameworkStatsLog.write(FrameworkStatsLog.ACTIVITY_ACTION_BLOCKED, /* caller_uid */ @@ -1265,7 +1291,7 @@ public class BackgroundActivityStartController { Slog.i(TAG, getDebugInfoForActivitySecurity("Clear Top", sourceRecord, targetRecord, targetTask, targetTaskTop, realCallingUid, balCode, shouldBlockActivityStart, - /* taskToFront */ true)); + /* taskToFront */ true, /* avoidMoveTaskToFront */ false)); } } @@ -1379,7 +1405,7 @@ public class BackgroundActivityStartController { private BlockActivityStart isTopActivityMatchingUidAbsentForAsm(@NonNull Task task, int uid, @Nullable ActivityRecord sourceRecord) { // If the source is visible, consider it 'top'. - if (sourceRecord != null && sourceRecord.isVisible()) { + if (sourceRecord != null && sourceRecord.isVisibleRequested()) { return new BlockActivityStart(false, false); } @@ -1389,6 +1415,12 @@ public class BackgroundActivityStartController { return new BlockActivityStart(false, false); } + // If UID is visible in target task, allow launch + if (task.forAllActivities((Predicate<ActivityRecord>) + ar -> ar.isUid(uid) && ar.isVisibleRequested())) { + return new BlockActivityStart(false, false); + } + // Consider the source activity, whether or not it is finishing. Do not consider any other // finishing activity. Predicate<ActivityRecord> topOfStackPredicate = (ar) -> ar.equals(sourceRecord) @@ -1480,27 +1512,26 @@ public class BackgroundActivityStartController { @Nullable ActivityRecord sourceRecord, @NonNull ActivityRecord targetRecord, @Nullable Task targetTask, @Nullable ActivityRecord targetTopActivity, int realCallingUid, @BalCode int balCode, - boolean blockActivityStartAndFeatureEnabled, boolean taskToFront) { + boolean blockActivityStartAndFeatureEnabled, boolean taskToFront, + boolean avoidMoveTaskToFront) { final String prefix = "[ASM] "; Function<ActivityRecord, String> recordToString = (ar) -> { if (ar == null) { return null; } - return (ar == sourceRecord ? " [source]=> " + + return (ar == sourceRecord ? " [source]=> " : ar == targetTopActivity ? " [ top ]=> " - : ar == targetRecord ? " [target]=> " - : " => ") - + ar - + " :: visible=" + ar.isVisible() - + ", finishing=" + ar.isFinishing() - + ", alwaysOnTop=" + ar.isAlwaysOnTop() - + ", taskFragment=" + ar.getTaskFragment(); + : ar == targetRecord ? " [target]=> " + : " => ") + + getDebugStringForActivityRecord(ar); }; StringJoiner joiner = new StringJoiner("\n"); joiner.add(prefix + "------ Activity Security " + action + " Debug Logging Start ------"); joiner.add(prefix + "Block Enabled: " + blockActivityStartAndFeatureEnabled); joiner.add(prefix + "ASM Version: " + ActivitySecurityModelFeatureFlags.ASM_VERSION); + joiner.add(prefix + "System Time: " + SystemClock.uptimeMillis()); boolean targetTaskMatchesSourceTask = targetTask != null && sourceRecord != null && sourceRecord.getTask() == targetTask; @@ -1512,6 +1543,8 @@ public class BackgroundActivityStartController { joiner.add(prefix + "Real Calling Uid Package: " + realCallingPackage); } else { joiner.add(prefix + "Source Record: " + recordToString.apply(sourceRecord)); + joiner.add(prefix + "Source Launch Package: " + sourceRecord.launchedFromPackage); + joiner.add(prefix + "Source Launch Intent: " + sourceRecord.intent); if (targetTaskMatchesSourceTask) { joiner.add(prefix + "Source/Target Task: " + sourceRecord.getTask()); joiner.add(prefix + "Source/Target Task Stack: "); @@ -1536,7 +1569,30 @@ public class BackgroundActivityStartController { joiner.add(prefix + "Target Record: " + recordToString.apply(targetRecord)); joiner.add(prefix + "Intent: " + targetRecord.intent); joiner.add(prefix + "TaskToFront: " + taskToFront); + joiner.add(prefix + "AvoidMoveToFront: " + avoidMoveTaskToFront); joiner.add(prefix + "BalCode: " + balCodeToString(balCode)); + joiner.add(prefix + "LastResumedActivity: " + + recordToString.apply(mService.mLastResumedActivity)); + + if (mTopFinishedActivity != null) { + joiner.add(prefix + "TopFinishedActivity: " + mTopFinishedActivity.mDebugInfo); + } + + if (!mTaskIdToFinishedActivity.isEmpty()) { + joiner.add(prefix + "TaskIdToFinishedActivity: "); + mTaskIdToFinishedActivity.values().forEach( + (fae) -> joiner.add(prefix + " " + fae.mDebugInfo)); + } + + if (balCode == BAL_ALLOW_VISIBLE_WINDOW || balCode == BAL_ALLOW_NON_APP_VISIBLE_WINDOW + || balCode == BAL_ALLOW_FOREGROUND) { + Task task = sourceRecord != null ? sourceRecord.getTask() : targetTask; + if (task != null && task.getDisplayArea() != null) { + joiner.add(prefix + "Tasks: "); + task.getDisplayArea().forAllTasks((Consumer<Task>) + t -> joiner.add(prefix + " T: " + t.toFullString())); + } + } joiner.add(prefix + "------ Activity Security " + action + " Debug Logging End ------"); return joiner.toString(); @@ -1620,7 +1676,7 @@ public class BackgroundActivityStartController { return; } - if (!finishActivity.mVisibleRequested + if (!finishActivity.isVisibleRequested() && finishActivity != finishActivity.getTask().getTopMostActivity()) { return; } @@ -1666,10 +1722,22 @@ public class BackgroundActivityStartController { } } + private static String getDebugStringForActivityRecord(ActivityRecord ar) { + return ar + + " :: visible=" + ar.isVisible() + + ", visibleRequested=" + ar.isVisibleRequested() + + ", finishing=" + ar.finishing + + ", alwaysOnTop=" + ar.isAlwaysOnTop() + + ", lastLaunchTime=" + ar.lastLaunchTime + + ", lastVisibleTime=" + ar.lastVisibleTime + + ", taskFragment=" + ar.getTaskFragment(); + } + private class FinishedActivityEntry { int mUid; int mTaskId; int mLaunchCount; + String mDebugInfo; FinishedActivityEntry(ActivityRecord ar) { FinishedActivityEntry entry = mTaskIdToFinishedActivity.get(ar.getTask().mTaskId); @@ -1677,6 +1745,7 @@ public class BackgroundActivityStartController { this.mUid = ar.getUid(); this.mTaskId = taskId; this.mLaunchCount = entry == null || !ar.isUid(entry.mUid) ? 1 : entry.mLaunchCount + 1; + this.mDebugInfo = getDebugStringForActivityRecord(ar); mService.mH.postDelayed(() -> { synchronized (mService.mGlobalLock) { diff --git a/services/core/java/com/android/server/wm/CompatModePackages.java b/services/core/java/com/android/server/wm/CompatModePackages.java index 1a8927ecf564..b795987f1d11 100644 --- a/services/core/java/com/android/server/wm/CompatModePackages.java +++ b/services/core/java/com/android/server/wm/CompatModePackages.java @@ -25,7 +25,6 @@ import static com.android.server.wm.CompatScaleProvider.COMPAT_SCALE_MODE_SYSTEM import android.annotation.NonNull; import android.app.ActivityManager; import android.app.AppGlobals; -import android.app.GameManagerInternal; import android.app.compat.CompatChanges; import android.compat.annotation.ChangeId; import android.compat.annotation.Disabled; @@ -52,7 +51,6 @@ import android.util.Xml; import com.android.internal.protolog.common.ProtoLog; import com.android.modules.utils.TypedXmlPullParser; import com.android.modules.utils.TypedXmlSerializer; -import com.android.server.LocalServices; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -345,7 +343,6 @@ public final class CompatModePackages { } private final ActivityTaskManagerService mService; - private GameManagerInternal mGameManager; private final AtomicFile mFile; private final HashMap<String, Integer> mPackages = new HashMap<>(); private final SparseBooleanArray mLegacyScreenCompatPackages = new SparseBooleanArray(); @@ -517,17 +514,6 @@ public final class CompatModePackages { } } final UserHandle userHandle = UserHandle.getUserHandleForUid(uid); - if (mGameManager == null) { - mGameManager = LocalServices.getService(GameManagerInternal.class); - } - if (mGameManager != null) { - final int userId = userHandle.getIdentifier(); - final float scalingFactor = mGameManager.getResolutionScalingFactor(packageName, - userId); - if (scalingFactor > 0) { - return 1f / scalingFactor; - } - } final boolean isDownscaledEnabled = CompatChanges.isChangeEnabled( DOWNSCALED, packageName, userHandle); diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java index 63ca5929e34d..e2bc59bb6550 100644 --- a/services/core/java/com/android/server/wm/DisplayPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayPolicy.java @@ -794,6 +794,9 @@ public class DisplayPolicy { } mService.mAtmService.mKeyguardController.updateDeferTransitionForAod( mAwake /* waiting */); + if (!awake) { + mDisplayContent.mWallpaperController.onDisplaySwitchFinished(); + } } } @@ -836,7 +839,8 @@ public class DisplayPolicy { mRemoteInsetsControllerControlsSystemBars = remoteInsetsControllerControlsSystemBars; } - public void screenTurnedOn(ScreenOnListener screenOnListener) { + /** Prepares to turn on screen. The given listener is used to notify that it is ready. */ + public void screenTurningOn(ScreenOnListener screenOnListener) { WindowProcessController visibleDozeUiProcess = null; synchronized (mLock) { mScreenOnEarly = true; @@ -858,6 +862,11 @@ public class DisplayPolicy { } } + /** It is called after {@link #finishScreenTurningOn}. This runs on PowerManager's thread. */ + public void screenTurnedOn() { + mDisplayContent.mWallpaperController.onDisplaySwitchFinished(); + } + public void screenTurnedOff() { synchronized (mLock) { mScreenOnEarly = false; diff --git a/services/core/java/com/android/server/wm/LetterboxUiController.java b/services/core/java/com/android/server/wm/LetterboxUiController.java index fcc1e5b62221..f2796895d639 100644 --- a/services/core/java/com/android/server/wm/LetterboxUiController.java +++ b/services/core/java/com/android/server/wm/LetterboxUiController.java @@ -148,7 +148,7 @@ import java.util.function.Predicate; final class LetterboxUiController { private static final Predicate<ActivityRecord> FIRST_OPAQUE_NOT_FINISHING_ACTIVITY_PREDICATE = - activityRecord -> activityRecord.fillsParent() && !activityRecord.isFinishing(); + ActivityRecord::occludesParent; private static final String TAG = TAG_WITH_CLASS_NAME ? "LetterboxUiController" : TAG_ATM; diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index 02b3f15979ce..587cc7489763 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -2783,6 +2783,9 @@ class RootWindowContainer extends WindowContainer<DisplayContent> } else { throw new RuntimeException("Create the same sleep token twice: " + token); } + if (isSwappingDisplay) { + display.mWallpaperController.onDisplaySwitchStarted(); + } return token; } diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java index 7d418eae6548..6371bb45ade9 100644 --- a/services/core/java/com/android/server/wm/TaskFragment.java +++ b/services/core/java/com/android/server/wm/TaskFragment.java @@ -732,17 +732,30 @@ class TaskFragment extends WindowContainer<WindowContainer> { return true; } + final AndroidPackage hostPackage = mAtmService.getPackageManagerInternalLocked() + .getPackage(uid); + + return hostPackage != null + && isAllowedToEmbedActivityInTrustedModeByHostPackage(a, hostPackage); + } + + @VisibleForTesting + boolean isAllowedToEmbedActivityInTrustedModeByHostPackage( + @NonNull ActivityRecord a, @NonNull AndroidPackage hostPackage) { + + // Known certs declared in the <activity> tag Set<String> knownActivityEmbeddingCerts = a.info.getKnownActivityEmbeddingCerts(); + + // If the activity-level value is specified, it takes precedence. Otherwise, we read the + // application-level value. if (knownActivityEmbeddingCerts.isEmpty()) { - // An application must either declare that it allows untrusted embedding, or specify - // a set of app certificates that are allowed to embed it in trusted mode. - return false; + // Known certs declared in the <application> tag + knownActivityEmbeddingCerts = a.info.applicationInfo.getKnownActivityEmbeddingCerts(); } - AndroidPackage hostPackage = mAtmService.getPackageManagerInternalLocked() - .getPackage(uid); - - return hostPackage != null && hostPackage.getSigningDetails().hasAncestorOrSelfWithDigest( + // An application must specify a set of app certificates that are allowed to embed it in + // trusted mode. + return hostPackage.getSigningDetails().hasAncestorOrSelfWithDigest( knownActivityEmbeddingCerts); } diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java index d68f932400a2..0fc62a758c5e 100644 --- a/services/core/java/com/android/server/wm/WallpaperController.java +++ b/services/core/java/com/android/server/wm/WallpaperController.java @@ -16,6 +16,7 @@ package com.android.server.wm; +import static android.app.WallpaperManager.COMMAND_DISPLAY_SWITCH; import static android.app.WallpaperManager.COMMAND_FREEZE; import static android.app.WallpaperManager.COMMAND_UNFREEZE; import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; @@ -120,6 +121,11 @@ class WallpaperController { private boolean mShouldOffsetWallpaperCenter; + /** + * Whether the wallpaper has been notified about a physical display switch event is started. + */ + private volatile boolean mIsWallpaperNotifiedOnDisplaySwitch; + private final Consumer<WindowState> mFindWallpapers = w -> { if (w.mAttrs.type == TYPE_WALLPAPER) { WallpaperWindowToken token = w.mToken.asWallpaperToken(); @@ -1083,6 +1089,52 @@ class WallpaperController { } /** + * Notifies the wallpaper that the display turns off when switching physical device. If the + * wallpaper is currently visible, its client visibility will be preserved until the display is + * confirmed to be off or on. + */ + void onDisplaySwitchStarted() { + mIsWallpaperNotifiedOnDisplaySwitch = notifyDisplaySwitch(true /* start */); + } + + /** + * Called when the screen has finished turning on or the device goes to sleep. This is no-op if + * the operation is not part of a display switch. + */ + void onDisplaySwitchFinished() { + // The method can be called outside WM lock (turned on), so only acquire lock if needed. + // This is to optimize the common cases that regular devices don't have display switch. + if (mIsWallpaperNotifiedOnDisplaySwitch) { + synchronized (mService.mGlobalLock) { + mIsWallpaperNotifiedOnDisplaySwitch = false; + notifyDisplaySwitch(false /* start */); + } + } + } + + private boolean notifyDisplaySwitch(boolean start) { + boolean notified = false; + for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) { + final WallpaperWindowToken token = mWallpaperTokens.get(curTokenNdx); + for (int i = token.getChildCount() - 1; i >= 0; i--) { + final WindowState w = token.getChildAt(i); + if (start && !w.mWinAnimator.getShown()) { + continue; + } + try { + w.mClient.dispatchWallpaperCommand(COMMAND_DISPLAY_SWITCH, 0 /* x */, 0 /* y */, + start ? 1 : 0 /* use z as start or finish */, + null /* bundle */, false /* sync */); + } catch (RemoteException e) { + Slog.w(TAG, "Failed to dispatch COMMAND_DISPLAY_SWITCH " + e); + } + notified = true; + } + } + return notified; + } + + /** * Each window can request a zoom, example: * - User is in overview, zoomed out. * - User also pulls down the shade. diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index f8ac8da710c8..9650b8bc2281 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -9156,55 +9156,63 @@ public class WindowManagerService extends IWindowManager.Stub if (fromWin == null || !fromWin.isFocused()) { return false; } - final TaskFragment fromFragment = fromWin.getTaskFragment(); - if (fromFragment == null) { - return false; - } - final TaskFragment adjacentFragment = fromFragment.getAdjacentTaskFragment(); - if (adjacentFragment == null || adjacentFragment.asTask() != null) { - // Don't move the focus to another task. - return false; - } - final Rect fromBounds = fromFragment.getBounds(); - final Rect adjacentBounds = adjacentFragment.getBounds(); - switch (direction) { - case View.FOCUS_LEFT: - if (adjacentBounds.left >= fromBounds.left) { - return false; - } - break; - case View.FOCUS_UP: - if (adjacentBounds.top >= fromBounds.top) { - return false; - } - break; - case View.FOCUS_RIGHT: - if (adjacentBounds.right <= fromBounds.right) { - return false; - } - break; - case View.FOCUS_DOWN: - if (adjacentBounds.bottom <= fromBounds.bottom) { - return false; - } - break; - case View.FOCUS_BACKWARD: - case View.FOCUS_FORWARD: - // These are not absolute directions. Skip checking the bounds. - break; - default: + return moveFocusToAdjacentWindow(fromWin, direction); + } + } + + boolean moveFocusToAdjacentWindow(WindowState fromWin, @FocusDirection int direction) { + final TaskFragment fromFragment = fromWin.getTaskFragment(); + if (fromFragment == null) { + return false; + } + final TaskFragment adjacentFragment = fromFragment.getAdjacentTaskFragment(); + if (adjacentFragment == null || adjacentFragment.asTask() != null) { + // Don't move the focus to another task. + return false; + } + if (adjacentFragment.isIsolatedNav()) { + // Don't move the focus if the adjacent TF is isolated navigation. + return false; + } + final Rect fromBounds = fromFragment.getBounds(); + final Rect adjacentBounds = adjacentFragment.getBounds(); + switch (direction) { + case View.FOCUS_LEFT: + if (adjacentBounds.left >= fromBounds.left) { return false; - } - final ActivityRecord topRunningActivity = adjacentFragment.topRunningActivity( - true /* focusableOnly */); - if (topRunningActivity == null) { - return false; - } - moveDisplayToTopInternal(topRunningActivity.getDisplayId()); - handleTaskFocusChange(topRunningActivity.getTask(), topRunningActivity); - if (fromWin.isFocused()) { + } + break; + case View.FOCUS_UP: + if (adjacentBounds.top >= fromBounds.top) { + return false; + } + break; + case View.FOCUS_RIGHT: + if (adjacentBounds.right <= fromBounds.right) { + return false; + } + break; + case View.FOCUS_DOWN: + if (adjacentBounds.bottom <= fromBounds.bottom) { + return false; + } + break; + case View.FOCUS_BACKWARD: + case View.FOCUS_FORWARD: + // These are not absolute directions. Skip checking the bounds. + break; + default: return false; - } + } + final ActivityRecord topRunningActivity = adjacentFragment.topRunningActivity( + true /* focusableOnly */); + if (topRunningActivity == null) { + return false; + } + moveDisplayToTopInternal(topRunningActivity.getDisplayId()); + handleTaskFocusChange(topRunningActivity.getTask(), topRunningActivity); + if (fromWin.isFocused()) { + return false; } return true; } diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp index 2b9bb7a4de87..2049331e8efe 100644 --- a/services/core/jni/com_android_server_input_InputManagerService.cpp +++ b/services/core/jni/com_android_server_input_InputManagerService.cpp @@ -46,6 +46,7 @@ #include <com_android_input_flags.h> #include <input/Input.h> #include <input/PointerController.h> +#include <input/PrintTools.h> #include <input/SpriteController.h> #include <inputflinger/InputManager.h> #include <limits.h> @@ -136,11 +137,10 @@ static struct { jmethodID getDoubleTapTimeout; jmethodID getLongPressTimeout; jmethodID getPointerLayer; - jmethodID getPointerIcon; + jmethodID getLoadedPointerIcon; jmethodID getKeyboardLayoutOverlay; jmethodID getDeviceAlias; jmethodID getTouchCalibrationForInputDevice; - jmethodID getContextForDisplay; jmethodID notifyDropWindow; jmethodID getParentSurfaceForPointers; } gServiceClassInfo; @@ -231,28 +231,14 @@ inline static T max(const T& a, const T& b) { return a > b ? a : b; } -static inline const char* toString(bool value) { - return value ? "true" : "false"; -} - -static void loadSystemIconAsSpriteWithPointerIcon(JNIEnv* env, jobject contextObj, - PointerIconStyle style, - PointerIcon* outPointerIcon, - SpriteIcon* outSpriteIcon) { - status_t status = android_view_PointerIcon_loadSystemIcon(env, - contextObj, style, outPointerIcon); - if (!status) { - outSpriteIcon->bitmap = outPointerIcon->bitmap.copy(ANDROID_BITMAP_FORMAT_RGBA_8888); - outSpriteIcon->style = outPointerIcon->style; - outSpriteIcon->hotSpotX = outPointerIcon->hotSpotX; - outSpriteIcon->hotSpotY = outPointerIcon->hotSpotY; - } -} - -static void loadSystemIconAsSprite(JNIEnv* env, jobject contextObj, PointerIconStyle style, - SpriteIcon* outSpriteIcon) { - PointerIcon pointerIcon; - loadSystemIconAsSpriteWithPointerIcon(env, contextObj, style, &pointerIcon, outSpriteIcon); +static SpriteIcon toSpriteIcon(PointerIcon pointerIcon) { + // As a minor optimization, do not make a copy of the PointerIcon bitmap here. The loaded + // PointerIcons are only cached by InputManagerService in java, so we can safely assume they + // will not be modified. This is safe because the native bitmap object holds a strong reference + // to the underlying bitmap, so even if the java object is released, we will still have access + // to it. + return SpriteIcon(pointerIcon.bitmap, pointerIcon.style, pointerIcon.hotSpotX, + pointerIcon.hotSpotY); } enum { @@ -299,7 +285,7 @@ public: void setSystemUiLightsOut(bool lightsOut); void setPointerDisplayId(int32_t displayId); void setPointerSpeed(int32_t speed); - void setMousePointerAccelerationEnabled(bool enabled); + void setMousePointerAccelerationEnabled(int32_t displayId, bool enabled); void setTouchpadPointerSpeed(int32_t speed); void setTouchpadNaturalScrollingEnabled(bool enabled); void setTouchpadTapToClickEnabled(bool enabled); @@ -315,6 +301,7 @@ public: bool setPointerIcon(std::variant<std::unique_ptr<SpriteIcon>, PointerIconStyle> icon, int32_t displayId, DeviceId deviceId, int32_t pointerId, const sp<IBinder>& inputToken); + void setPointerIconVisibility(int32_t displayId, bool visible); void setMotionClassifierEnabled(bool enabled); std::optional<std::string> getBluetoothAddress(int32_t deviceId); void setStylusButtonMotionEventsEnabled(bool enabled); @@ -411,8 +398,8 @@ private: // Pointer speed. int32_t pointerSpeed{0}; - // True if pointer acceleration is enabled for mice. - bool mousePointerAccelerationEnabled{true}; + // Displays on which its associated mice will have pointer acceleration disabled. + std::set<int32_t> displaysWithMousePointerAccelerationDisabled{}; // True if pointer gestures are enabled. bool pointerGesturesEnabled{true}; @@ -473,6 +460,7 @@ private: void forEachPointerControllerLocked(std::function<void(PointerController&)> apply) REQUIRES(mLock); + PointerIcon loadPointerIcon(JNIEnv* env, int32_t displayId, PointerIconStyle type); static inline JNIEnv* jniEnv() { return AndroidRuntime::getJNIEnv(); } }; @@ -502,8 +490,8 @@ void NativeInputManager::dump(std::string& dump) { dump += StringPrintf(INDENT "System UI Lights Out: %s\n", toString(mLocked.systemUiLightsOut)); dump += StringPrintf(INDENT "Pointer Speed: %" PRId32 "\n", mLocked.pointerSpeed); - dump += StringPrintf(INDENT "Mouse Pointer Acceleration: %s\n", - mLocked.mousePointerAccelerationEnabled ? "Enabled" : "Disabled"); + dump += StringPrintf(INDENT "Display with Mouse Pointer Acceleration Disabled: %s\n", + dumpSet(mLocked.displaysWithMousePointerAccelerationDisabled).c_str()); dump += StringPrintf(INDENT "Pointer Gestures Enabled: %s\n", toString(mLocked.pointerGesturesEnabled)); dump += StringPrintf(INDENT "Show Touches: %s\n", toString(mLocked.showTouches)); @@ -686,11 +674,13 @@ void NativeInputManager::getReaderConfiguration(InputReaderConfiguration* outCon std::scoped_lock _l(mLock); outConfig->mousePointerSpeed = mLocked.pointerSpeed; - outConfig->mousePointerAccelerationEnabled = mLocked.mousePointerAccelerationEnabled; - outConfig->pointerVelocityControlParameters.scale = exp2f(mLocked.pointerSpeed - * POINTER_SPEED_EXPONENT); + outConfig->displaysWithMousePointerAccelerationDisabled = + mLocked.displaysWithMousePointerAccelerationDisabled; + outConfig->pointerVelocityControlParameters.scale = + exp2f(mLocked.pointerSpeed * POINTER_SPEED_EXPONENT); outConfig->pointerVelocityControlParameters.acceleration = - mLocked.mousePointerAccelerationEnabled + mLocked.displaysWithMousePointerAccelerationDisabled.count( + mLocked.pointerDisplayId) == 0 ? android::os::IInputConstants::DEFAULT_POINTER_ACCELERATION : 1; outConfig->pointerGesturesEnabled = mLocked.pointerGesturesEnabled; @@ -753,6 +743,27 @@ void NativeInputManager::forEachPointerControllerLocked( } } +PointerIcon NativeInputManager::loadPointerIcon(JNIEnv* env, int32_t displayId, + PointerIconStyle type) { + if (type == PointerIconStyle::TYPE_CUSTOM) { + LOG(FATAL) << __func__ << ": Cannot load non-system icon type"; + } + if (type == PointerIconStyle::TYPE_NULL) { + return PointerIcon(); + } + + ScopedLocalRef<jobject> pointerIconObj(env, + env->CallObjectMethod(mServiceObj, + gServiceClassInfo + .getLoadedPointerIcon, + displayId, type)); + if (checkAndClearExceptionFromCallback(env, "getLoadedPointerIcon")) { + LOG(FATAL) << __func__ << ": Failed to load pointer icon"; + } + + return android_view_PointerIcon_toNative(env, pointerIconObj.get()); +} + // TODO(b/293587049): Remove the old way of obtaining PointerController when the // PointerChoreographer refactoring is complete. std::shared_ptr<PointerControllerInterface> NativeInputManager::obtainPointerController( @@ -1213,16 +1224,23 @@ void NativeInputManager::setPointerSpeed(int32_t speed) { InputReaderConfiguration::Change::POINTER_SPEED); } -void NativeInputManager::setMousePointerAccelerationEnabled(bool enabled) { +void NativeInputManager::setMousePointerAccelerationEnabled(int32_t displayId, bool enabled) { { // acquire lock std::scoped_lock _l(mLock); - if (mLocked.mousePointerAccelerationEnabled == enabled) { + const bool oldEnabled = + mLocked.displaysWithMousePointerAccelerationDisabled.count(displayId) == 0; + if (oldEnabled == enabled) { return; } - ALOGI("Setting mouse pointer acceleration to %s", toString(enabled)); - mLocked.mousePointerAccelerationEnabled = enabled; + ALOGI("Setting mouse pointer acceleration to %s on display %d", toString(enabled), + displayId); + if (enabled) { + mLocked.displaysWithMousePointerAccelerationDisabled.erase(displayId); + } else { + mLocked.displaysWithMousePointerAccelerationDisabled.emplace(displayId); + } } // release lock mInputManager->getReader().requestRefreshConfiguration( @@ -1386,6 +1404,13 @@ bool NativeInputManager::setPointerIcon( return mInputManager->getChoreographer().setPointerIcon(std::move(icon), displayId, deviceId); } +void NativeInputManager::setPointerIconVisibility(int32_t displayId, bool visible) { + if (!ENABLE_POINTER_CHOREOGRAPHER) { + return; + } + mInputManager->getChoreographer().setPointerIconVisibility(displayId, visible); +} + TouchAffineTransformation NativeInputManager::getTouchAffineTransformation( JNIEnv *env, jfloatArray matrixArr) { ATRACE_CALL(); @@ -1670,40 +1695,19 @@ void NativeInputManager::setPointerCapture(const PointerCaptureRequest& request) void NativeInputManager::loadPointerIcon(SpriteIcon* icon, int32_t displayId) { ATRACE_CALL(); JNIEnv* env = jniEnv(); - - ScopedLocalRef<jobject> pointerIconObj(env, env->CallObjectMethod( - mServiceObj, gServiceClassInfo.getPointerIcon, displayId)); - if (checkAndClearExceptionFromCallback(env, "getPointerIcon")) { - return; - } - - ScopedLocalRef<jobject> displayContext(env, env->CallObjectMethod( - mServiceObj, gServiceClassInfo.getContextForDisplay, displayId)); - - PointerIcon pointerIcon; - status_t status = android_view_PointerIcon_load(env, pointerIconObj.get(), - displayContext.get(), &pointerIcon); - if (!status && !pointerIcon.isNullIcon()) { - *icon = SpriteIcon( - pointerIcon.bitmap, pointerIcon.style, pointerIcon.hotSpotX, pointerIcon.hotSpotY); - } else { - *icon = SpriteIcon(); - } + *icon = toSpriteIcon(loadPointerIcon(env, displayId, PointerIconStyle::TYPE_ARROW)); } void NativeInputManager::loadPointerResources(PointerResources* outResources, int32_t displayId) { ATRACE_CALL(); JNIEnv* env = jniEnv(); - ScopedLocalRef<jobject> displayContext(env, env->CallObjectMethod( - mServiceObj, gServiceClassInfo.getContextForDisplay, displayId)); - - loadSystemIconAsSprite(env, displayContext.get(), PointerIconStyle::TYPE_SPOT_HOVER, - &outResources->spotHover); - loadSystemIconAsSprite(env, displayContext.get(), PointerIconStyle::TYPE_SPOT_TOUCH, - &outResources->spotTouch); - loadSystemIconAsSprite(env, displayContext.get(), PointerIconStyle::TYPE_SPOT_ANCHOR, - &outResources->spotAnchor); + outResources->spotHover = + toSpriteIcon(loadPointerIcon(env, displayId, PointerIconStyle::TYPE_SPOT_HOVER)); + outResources->spotTouch = + toSpriteIcon(loadPointerIcon(env, displayId, PointerIconStyle::TYPE_SPOT_TOUCH)); + outResources->spotAnchor = + toSpriteIcon(loadPointerIcon(env, displayId, PointerIconStyle::TYPE_SPOT_ANCHOR)); } void NativeInputManager::loadAdditionalMouseResources( @@ -1712,15 +1716,11 @@ void NativeInputManager::loadAdditionalMouseResources( ATRACE_CALL(); JNIEnv* env = jniEnv(); - ScopedLocalRef<jobject> displayContext(env, env->CallObjectMethod( - mServiceObj, gServiceClassInfo.getContextForDisplay, displayId)); - for (int32_t iconId = static_cast<int32_t>(PointerIconStyle::TYPE_CONTEXT_MENU); iconId <= static_cast<int32_t>(PointerIconStyle::TYPE_HANDWRITING); ++iconId) { const PointerIconStyle pointerIconStyle = static_cast<PointerIconStyle>(iconId); - PointerIcon pointerIcon; - loadSystemIconAsSpriteWithPointerIcon(env, displayContext.get(), pointerIconStyle, - &pointerIcon, &((*outResources)[pointerIconStyle])); + PointerIcon pointerIcon = loadPointerIcon(env, displayId, pointerIconStyle); + (*outResources)[pointerIconStyle] = toSpriteIcon(pointerIcon); if (!pointerIcon.bitmapFrames.empty()) { PointerAnimation& animationData = (*outAnimationResources)[pointerIconStyle]; size_t numFrames = pointerIcon.bitmapFrames.size() + 1; @@ -1737,8 +1737,9 @@ void NativeInputManager::loadAdditionalMouseResources( } } } - loadSystemIconAsSprite(env, displayContext.get(), PointerIconStyle::TYPE_NULL, - &((*outResources)[PointerIconStyle::TYPE_NULL])); + + (*outResources)[PointerIconStyle::TYPE_NULL] = + toSpriteIcon(loadPointerIcon(env, displayId, PointerIconStyle::TYPE_NULL)); } PointerIconStyle NativeInputManager::getDefaultPointerIconId() { @@ -2181,10 +2182,10 @@ static void nativeSetPointerSpeed(JNIEnv* env, jobject nativeImplObj, jint speed } static void nativeSetMousePointerAccelerationEnabled(JNIEnv* env, jobject nativeImplObj, - jboolean enabled) { + jint displayId, jboolean enabled) { NativeInputManager* im = getNativeInputManager(env, nativeImplObj); - im->setMousePointerAccelerationEnabled(enabled); + im->setMousePointerAccelerationEnabled(displayId, enabled); } static void nativeSetTouchpadPointerSpeed(JNIEnv* env, jobject nativeImplObj, jint speed) { @@ -2539,17 +2540,7 @@ static void nativeReloadPointerIcons(JNIEnv* env, jobject nativeImplObj) { static void nativeSetCustomPointerIcon(JNIEnv* env, jobject nativeImplObj, jobject iconObj) { NativeInputManager* im = getNativeInputManager(env, nativeImplObj); - - PointerIcon pointerIcon; - status_t result = android_view_PointerIcon_getLoadedIcon(env, iconObj, &pointerIcon); - if (result) { - jniThrowRuntimeException(env, "Failed to load custom pointer icon."); - return; - } - - SpriteIcon spriteIcon(pointerIcon.bitmap.copy(ANDROID_BITMAP_FORMAT_RGBA_8888), - pointerIcon.style, pointerIcon.hotSpotX, pointerIcon.hotSpotY); - im->setCustomPointerIcon(spriteIcon); + im->setCustomPointerIcon(toSpriteIcon(android_view_PointerIcon_toNative(env, iconObj))); } static bool nativeSetPointerIcon(JNIEnv* env, jobject nativeImplObj, jobject iconObj, @@ -2557,12 +2548,7 @@ static bool nativeSetPointerIcon(JNIEnv* env, jobject nativeImplObj, jobject ico jobject inputTokenObj) { NativeInputManager* im = getNativeInputManager(env, nativeImplObj); - PointerIcon pointerIcon; - status_t result = android_view_PointerIcon_getLoadedIcon(env, iconObj, &pointerIcon); - if (result) { - jniThrowRuntimeException(env, "Failed to load pointer icon."); - return false; - } + PointerIcon pointerIcon = android_view_PointerIcon_toNative(env, iconObj); std::variant<std::unique_ptr<SpriteIcon>, PointerIconStyle> icon; if (pointerIcon.style == PointerIconStyle::TYPE_CUSTOM) { @@ -2578,6 +2564,13 @@ static bool nativeSetPointerIcon(JNIEnv* env, jobject nativeImplObj, jobject ico ibinderForJavaObject(env, inputTokenObj)); } +static void nativeSetPointerIconVisibility(JNIEnv* env, jobject nativeImplObj, jint displayId, + jboolean visible) { + NativeInputManager* im = getNativeInputManager(env, nativeImplObj); + + im->setPointerIconVisibility(displayId, visible); +} + static jboolean nativeCanDispatchToDisplay(JNIEnv* env, jobject nativeImplObj, jint deviceId, jint displayId) { NativeInputManager* im = getNativeInputManager(env, nativeImplObj); @@ -2819,7 +2812,7 @@ static const JNINativeMethod gInputManagerMethods[] = { (void*)nativeTransferTouchFocus}, {"transferTouch", "(Landroid/os/IBinder;I)Z", (void*)nativeTransferTouch}, {"setPointerSpeed", "(I)V", (void*)nativeSetPointerSpeed}, - {"setMousePointerAccelerationEnabled", "(Z)V", + {"setMousePointerAccelerationEnabled", "(IZ)V", (void*)nativeSetMousePointerAccelerationEnabled}, {"setTouchpadPointerSpeed", "(I)V", (void*)nativeSetTouchpadPointerSpeed}, {"setTouchpadNaturalScrollingEnabled", "(Z)V", @@ -2856,6 +2849,7 @@ static const JNINativeMethod gInputManagerMethods[] = { (void*)nativeSetCustomPointerIcon}, {"setPointerIcon", "(Landroid/view/PointerIcon;IIILandroid/os/IBinder;)Z", (void*)nativeSetPointerIcon}, + {"setPointerIconVisibility", "(IZ)V", (void*)nativeSetPointerIconVisibility}, {"canDispatchToDisplay", "(II)Z", (void*)nativeCanDispatchToDisplay}, {"notifyPortAssociationsChanged", "()V", (void*)nativeNotifyPortAssociationsChanged}, {"changeUniqueIdAssociation", "()V", (void*)nativeChangeUniqueIdAssociation}, @@ -3018,8 +3012,8 @@ int register_android_server_InputManager(JNIEnv* env) { GET_METHOD_ID(gServiceClassInfo.getPointerLayer, clazz, "getPointerLayer", "()I"); - GET_METHOD_ID(gServiceClassInfo.getPointerIcon, clazz, - "getPointerIcon", "(I)Landroid/view/PointerIcon;"); + GET_METHOD_ID(gServiceClassInfo.getLoadedPointerIcon, clazz, "getLoadedPointerIcon", + "(II)Landroid/view/PointerIcon;"); GET_METHOD_ID(gServiceClassInfo.getKeyboardLayoutOverlay, clazz, "getKeyboardLayoutOverlay", "(Landroid/hardware/input/InputDeviceIdentifier;Ljava/lang/String;Ljava/lang/" @@ -3032,9 +3026,6 @@ int register_android_server_InputManager(JNIEnv* env) { "getTouchCalibrationForInputDevice", "(Ljava/lang/String;I)Landroid/hardware/input/TouchCalibration;"); - GET_METHOD_ID(gServiceClassInfo.getContextForDisplay, clazz, "getContextForDisplay", - "(I)Landroid/content/Context;"); - GET_METHOD_ID(gServiceClassInfo.getParentSurfaceForPointers, clazz, "getParentSurfaceForPointers", "(I)J"); diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp index 11c40d7bcd9b..9c033e25c04e 100644 --- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp +++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp @@ -675,7 +675,8 @@ static jboolean android_location_gnss_hal_GnssNative_start_measurement_collectio options.enableCorrVecOutputs = enableCorrVecOutputs; options.intervalMs = intervalMs; - return gnssMeasurementIface->setCallback(std::make_unique<gnss::GnssMeasurementCallback>(), + return gnssMeasurementIface->setCallback(std::make_unique<gnss::GnssMeasurementCallback>( + gnssMeasurementIface->getInterfaceVersion()), options); } diff --git a/services/core/jni/gnss/Gnss.cpp b/services/core/jni/gnss/Gnss.cpp index 8934c3a6abde..da8928b5f97f 100644 --- a/services/core/jni/gnss/Gnss.cpp +++ b/services/core/jni/gnss/Gnss.cpp @@ -196,7 +196,8 @@ void GnssHal::linkToDeath() { jboolean GnssHal::setCallback() { if (gnssHalAidl != nullptr) { - sp<IGnssCallbackAidl> gnssCbIfaceAidl = new GnssCallbackAidl(); + sp<IGnssCallbackAidl> gnssCbIfaceAidl = + new GnssCallbackAidl(gnssHalAidl->getInterfaceVersion()); auto status = gnssHalAidl->setCallback(gnssCbIfaceAidl); if (!checkAidlStatus(status, "IGnssAidl setCallback() failed.")) { return JNI_FALSE; diff --git a/services/core/jni/gnss/GnssCallback.cpp b/services/core/jni/gnss/GnssCallback.cpp index 60eed8e6d716..3d598f7a7203 100644 --- a/services/core/jni/gnss/GnssCallback.cpp +++ b/services/core/jni/gnss/GnssCallback.cpp @@ -120,7 +120,7 @@ void Gnss_class_init_once(JNIEnv* env, jclass& clazz) { Status GnssCallbackAidl::gnssSetCapabilitiesCb(const int capabilities) { ALOGD("%s: %du\n", __func__, capabilities); - bool isAdrCapabilityKnown = (getInterfaceVersion() >= 3) ? true : false; + bool isAdrCapabilityKnown = (interfaceVersion >= 3) ? true : false; JNIEnv* env = getJniEnv(); env->CallVoidMethod(mCallbacksObj, method_setTopHalCapabilities, capabilities, isAdrCapabilityKnown); @@ -178,7 +178,7 @@ Status GnssCallbackAidl::gnssLocationCb(const hardware::gnss::GnssLocation& loca Status GnssCallbackAidl::gnssNmeaCb(const int64_t timestamp, const std::string& nmea) { // In AIDL v1, if no listener is registered, do not report nmea to the framework. - if (getInterfaceVersion() <= 1) { + if (interfaceVersion <= 1) { if (!isNmeaRegistered) { return Status::ok(); } diff --git a/services/core/jni/gnss/GnssCallback.h b/services/core/jni/gnss/GnssCallback.h index 33acec8b5660..0622e533e5b5 100644 --- a/services/core/jni/gnss/GnssCallback.h +++ b/services/core/jni/gnss/GnssCallback.h @@ -60,6 +60,7 @@ void Gnss_class_init_once(JNIEnv* env, jclass& clazz); */ class GnssCallbackAidl : public hardware::gnss::BnGnssCallback { public: + GnssCallbackAidl(int version) : interfaceVersion(version){}; binder::Status gnssSetCapabilitiesCb(const int capabilities) override; binder::Status gnssSetSignalTypeCapabilitiesCb( const std::vector<android::hardware::gnss::GnssSignalType>& signalTypes) override; @@ -73,6 +74,9 @@ public: binder::Status gnssRequestTimeCb() override; binder::Status gnssRequestLocationCb(const bool independentFromGnss, const bool isUserEmergency) override; + +private: + const int interfaceVersion; }; /* diff --git a/services/core/jni/gnss/GnssMeasurement.h b/services/core/jni/gnss/GnssMeasurement.h index 7a95db8ed7b6..20400fd8f587 100644 --- a/services/core/jni/gnss/GnssMeasurement.h +++ b/services/core/jni/gnss/GnssMeasurement.h @@ -41,6 +41,7 @@ public: const std::unique_ptr<GnssMeasurementCallback>& callback, const android::hardware::gnss::IGnssMeasurementInterface::Options& options) = 0; virtual jboolean close() = 0; + virtual int getInterfaceVersion() = 0; }; class GnssMeasurement : public GnssMeasurementInterface { @@ -50,6 +51,9 @@ public: const std::unique_ptr<GnssMeasurementCallback>& callback, const android::hardware::gnss::IGnssMeasurementInterface::Options& options) override; jboolean close() override; + int getInterfaceVersion() override { + return mIGnssMeasurement->getInterfaceVersion(); + } private: const sp<android::hardware::gnss::IGnssMeasurementInterface> mIGnssMeasurement; @@ -63,6 +67,9 @@ public: const std::unique_ptr<GnssMeasurementCallback>& callback, const android::hardware::gnss::IGnssMeasurementInterface::Options& options) override; jboolean close() override; + int getInterfaceVersion() override { + return 0; + } private: const sp<android::hardware::gnss::V1_0::IGnssMeasurement> mIGnssMeasurement_V1_0; diff --git a/services/core/jni/gnss/GnssMeasurementCallback.cpp b/services/core/jni/gnss/GnssMeasurementCallback.cpp index 2982546bfa47..ebab4c342ca0 100644 --- a/services/core/jni/gnss/GnssMeasurementCallback.cpp +++ b/services/core/jni/gnss/GnssMeasurementCallback.cpp @@ -392,7 +392,7 @@ void GnssMeasurementCallbackAidl::translateAndSetGnssData(const GnssData& data) jobjectArray gnssAgcArray = nullptr; gnssAgcArray = translateAllGnssAgcs(env, data.gnssAgcs); - if (this->getInterfaceVersion() >= 3) { + if (interfaceVersion >= 3) { setMeasurementData(env, mCallbacksObj, clock, measurementArray, gnssAgcArray, /*hasIsFullTracking=*/true, data.isFullTracking); } else { @@ -467,7 +467,7 @@ void GnssMeasurementCallbackAidl::translateSingleGnssMeasurement(JNIEnv* env, satellitePvt.tropoDelayMeters); } - if (this->getInterfaceVersion() >= 2) { + if (interfaceVersion >= 2) { callObjectMethodIgnoringResult(env, satellitePvtBuilderObject, method_satellitePvtBuilderSetTimeOfClock, satellitePvt.timeOfClockSeconds); diff --git a/services/core/jni/gnss/GnssMeasurementCallback.h b/services/core/jni/gnss/GnssMeasurementCallback.h index b3de486e6fa9..3cb47ce2fe18 100644 --- a/services/core/jni/gnss/GnssMeasurementCallback.h +++ b/services/core/jni/gnss/GnssMeasurementCallback.h @@ -53,7 +53,8 @@ void setMeasurementData(JNIEnv* env, jobject& callbacksObj, jobject clock, class GnssMeasurementCallbackAidl : public hardware::gnss::BnGnssMeasurementCallback { public: - GnssMeasurementCallbackAidl() : mCallbacksObj(getCallbacksObj()) {} + GnssMeasurementCallbackAidl(int version) + : mCallbacksObj(getCallbacksObj()), interfaceVersion(version) {} android::binder::Status gnssMeasurementCb(const hardware::gnss::GnssData& data) override; private: @@ -71,6 +72,7 @@ private: void translateGnssClock(JNIEnv* env, const hardware::gnss::GnssData& data, JavaObject& object); jobject& mCallbacksObj; + const int interfaceVersion; }; /* @@ -110,10 +112,10 @@ private: class GnssMeasurementCallback { public: - GnssMeasurementCallback() {} + GnssMeasurementCallback(int version) : interfaceVersion(version) {} sp<GnssMeasurementCallbackAidl> getAidl() { if (callbackAidl == nullptr) { - callbackAidl = sp<GnssMeasurementCallbackAidl>::make(); + callbackAidl = sp<GnssMeasurementCallbackAidl>::make(interfaceVersion); } return callbackAidl; } @@ -128,6 +130,7 @@ public: private: sp<GnssMeasurementCallbackAidl> callbackAidl; sp<GnssMeasurementCallbackHidl> callbackHidl; + const int interfaceVersion; }; template <class T> diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/PersonalAppsSuspensionHelper.java b/services/devicepolicy/java/com/android/server/devicepolicy/PersonalAppsSuspensionHelper.java index 532823ad8367..e8c5658ca941 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/PersonalAppsSuspensionHelper.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/PersonalAppsSuspensionHelper.java @@ -17,6 +17,7 @@ package com.android.server.devicepolicy; import static android.accessibilityservice.AccessibilityServiceInfo.FEEDBACK_ALL_MASK; +import static android.app.admin.flags.Flags.defaultSmsPersonalAppSuspensionFixEnabled; import android.accessibilityservice.AccessibilityServiceInfo; import android.annotation.Nullable; @@ -42,6 +43,7 @@ import android.view.accessibility.IAccessibilityManager; import android.view.inputmethod.InputMethodInfo; import com.android.internal.R; +import com.android.internal.telephony.SmsApplication; import com.android.server.inputmethod.InputMethodManagerInternal; import com.android.server.utils.Slogf; @@ -97,7 +99,7 @@ public final class PersonalAppsSuspensionHelper { result.removeAll(getSystemLauncherPackages()); result.removeAll(getAccessibilityServices()); result.removeAll(getInputMethodPackages()); - result.remove(Telephony.Sms.getDefaultSmsPackage(mContext)); + result.remove(getDefaultSmsPackage()); result.remove(getSettingsPackageName()); final String[] unsuspendablePackages = @@ -202,6 +204,17 @@ public final class PersonalAppsSuspensionHelper { return resolveInfos != null && !resolveInfos.isEmpty(); } + private String getDefaultSmsPackage() { + //TODO(b/319449037): Unflag the following change. + if (defaultSmsPersonalAppSuspensionFixEnabled()) { + return SmsApplication.getDefaultSmsApplicationAsUser( + mContext, /*updateIfNeeded=*/ false, mContext.getUser()) + .getPackageName(); + } else { + return Telephony.Sms.getDefaultSmsPackage(mContext); + } + } + void dump(IndentingPrintWriter pw) { pw.println("PersonalAppsSuspensionHelper"); @@ -212,7 +225,7 @@ public final class PersonalAppsSuspensionHelper { DevicePolicyManagerService.dumpApps(pw, "accessibility services", getAccessibilityServices()); DevicePolicyManagerService.dumpApps(pw, "input method packages", getInputMethodPackages()); - pw.printf("SMS package: %s\n", Telephony.Sms.getDefaultSmsPackage(mContext)); + pw.printf("SMS package: %s\n", getDefaultSmsPackage()); pw.printf("Settings package: %s\n", getSettingsPackageName()); DevicePolicyManagerService.dumpApps(pw, "Packages subject to suspension", getPersonalAppsForSuspension()); diff --git a/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt b/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt index 62d2d7ee848a..4c74878dab70 100644 --- a/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt +++ b/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt @@ -22,6 +22,7 @@ import android.content.pm.PermissionGroupInfo import android.content.pm.PermissionInfo import android.content.pm.SigningDetails import android.os.Build +import android.permission.flags.Flags import android.util.Slog import com.android.internal.os.RoSystemProperties import com.android.internal.pm.permission.CompatibilityPermissionInfo @@ -1197,15 +1198,80 @@ class AppIdPermissionPolicy : SchemePolicy() { newState.externalState.packageStates[PLATFORM_PACKAGE_NAME]!! .androidPackage!! .signingDetails - return sourceSigningDetails?.hasCommonSignerWithCapability( - packageSigningDetails, - SigningDetails.CertCapabilities.PERMISSION - ) == true || - packageSigningDetails.hasAncestorOrSelf(platformSigningDetails) || - platformSigningDetails.checkCapability( + val hasCommonSigner = + sourceSigningDetails?.hasCommonSignerWithCapability( packageSigningDetails, SigningDetails.CertCapabilities.PERMISSION - ) + ) == true || + packageSigningDetails.hasAncestorOrSelf(platformSigningDetails) || + platformSigningDetails.checkCapability( + packageSigningDetails, + SigningDetails.CertCapabilities.PERMISSION + ) + if (!Flags.signaturePermissionAllowlistEnabled()) { + return hasCommonSigner; + } + if (!hasCommonSigner) { + return false + } + // A platform signature permission also needs to be allowlisted on non-debuggable builds. + if (permission.packageName == PLATFORM_PACKAGE_NAME) { + val isRequestedByFactoryApp = + if (packageState.isSystem) { + // For updated system applications, a signature permission still needs to be + // allowlisted if it wasn't requested by the original application. + if (packageState.isUpdatedSystemApp) { + val disabledSystemPackage = + newState.externalState.disabledSystemPackageStates[ + packageState.packageName] + ?.androidPackage + disabledSystemPackage != null && + permission.name in disabledSystemPackage.requestedPermissions + } else { + true + } + } else { + false + } + if ( + !(isRequestedByFactoryApp || + getSignaturePermissionAllowlistState(packageState, permission.name) == true) + ) { + Slog.w( + LOG_TAG, + "Signature permission ${permission.name} for package" + + " ${packageState.packageName} (${packageState.path}) not in" + + " signature permission allowlist" + ) + if (!Build.isDebuggable()) { + return false + } + } + } + return true + } + + private fun MutateStateScope.getSignaturePermissionAllowlistState( + packageState: PackageState, + permissionName: String + ): Boolean? { + val permissionAllowlist = newState.externalState.permissionAllowlist + val packageName = packageState.packageName + return when { + packageState.isVendor || packageState.isOdm -> + permissionAllowlist.getVendorSignatureAppAllowlistState(packageName, permissionName) + packageState.isProduct -> + permissionAllowlist.getProductSignatureAppAllowlistState( + packageName, + permissionName + ) + packageState.isSystemExt -> + permissionAllowlist.getSystemExtSignatureAppAllowlistState( + packageName, + permissionName + ) + else -> permissionAllowlist.getSignatureAppAllowlistState(packageName, permissionName) + } } private fun MutateStateScope.checkPrivilegedPermissionAllowlist( diff --git a/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt b/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt index f469ab547763..097d73a9a05b 100644 --- a/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt +++ b/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt @@ -960,8 +960,8 @@ class PermissionService(private val service: AccessCheckingService) : if (permissionName !in androidPackage.requestedPermissions && oldFlags == 0) { if (reportError) { - throw SecurityException( - "Permission $permissionName isn't requested by package $packageName" + Slog.e( + LOG_TAG, "Permission $permissionName isn't requested by package $packageName" ) } return diff --git a/services/tests/BackgroundInstallControlServiceTests/host/Android.bp b/services/tests/BackgroundInstallControlServiceTests/host/Android.bp index 4fcdbfc21f6c..d479e52f92d8 100644 --- a/services/tests/BackgroundInstallControlServiceTests/host/Android.bp +++ b/services/tests/BackgroundInstallControlServiceTests/host/Android.bp @@ -11,7 +11,6 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. - package { // See: http://go/android-license-faq // A large-scale-change added 'default_applicable_licenses' to import diff --git a/services/tests/BackgroundInstallControlServiceTests/host/src/com/android/server/pm/test/BackgroundInstallControlServiceHostTest.java b/services/tests/BackgroundInstallControlServiceTests/host/src/com/android/server/pm/test/BackgroundInstallControlServiceHostTest.java index 74506076d82f..c99e7129853b 100644 --- a/services/tests/BackgroundInstallControlServiceTests/host/src/com/android/server/pm/test/BackgroundInstallControlServiceHostTest.java +++ b/services/tests/BackgroundInstallControlServiceTests/host/src/com/android/server/pm/test/BackgroundInstallControlServiceHostTest.java @@ -41,17 +41,26 @@ public final class BackgroundInstallControlServiceHostTest extends BaseHostJUnit private static final String MOCK_APK_FILE_1 = "BackgroundInstallControlMockApp1.apk"; private static final String MOCK_APK_FILE_2 = "BackgroundInstallControlMockApp2.apk"; + // TODO: Move the silent installs to test-app using {@link + // BackgroundInstallControlServiceTest#installPackage(String, String)} and remove deviceConfig + // branch in BICS. + // b/310983905 @Test public void testGetMockBackgroundInstalledPackages() throws Exception { - installPackage(TEST_DATA_DIR + MOCK_APK_FILE_1); + installPackage(TEST_DATA_DIR + MOCK_APK_FILE_1); installPackage(TEST_DATA_DIR + MOCK_APK_FILE_2); assertThat(getDevice().getAppPackageInfo(MOCK_PACKAGE_NAME_1)).isNotNull(); assertThat(getDevice().getAppPackageInfo(MOCK_PACKAGE_NAME_2)).isNotNull(); - assertThat(getDevice().setProperty("debug.transparency.bg-install-apps", - MOCK_PACKAGE_NAME_1 + "," + MOCK_PACKAGE_NAME_2)).isTrue(); - runDeviceTest("testGetMockBackgroundInstalledPackages"); + assertThat( + getDevice() + .setProperty( + "debug.transparency.bg-install-apps", + MOCK_PACKAGE_NAME_1 + "," + MOCK_PACKAGE_NAME_2)) + .isTrue(); + runDeviceTest( + "BackgroundInstallControlServiceTest", "testGetMockBackgroundInstalledPackages"); assertThat(getDevice().uninstallPackage(MOCK_PACKAGE_NAME_1)).isNull(); assertThat(getDevice().uninstallPackage(MOCK_PACKAGE_NAME_2)).isNull(); @@ -65,10 +74,10 @@ public final class BackgroundInstallControlServiceHostTest extends BaseHostJUnit assertThat(result.getStatus() == CommandStatus.SUCCESS).isTrue(); } - private void runDeviceTest(String method) throws DeviceNotAvailableException { + private void runDeviceTest(String testName, String method) throws DeviceNotAvailableException { var options = new DeviceTestRunOptions(PACKAGE_NAME); - options.setTestClassName(PACKAGE_NAME + ".BackgroundInstallControlServiceTest"); + options.setTestClassName(PACKAGE_NAME + "." + testName); options.setTestMethodName(method); runDeviceTests(options); } -} +}
\ No newline at end of file diff --git a/services/tests/BackgroundInstallControlServiceTests/host/test-app/BackgroundInstallControlServiceTestApp/AndroidManifest.xml b/services/tests/BackgroundInstallControlServiceTests/host/test-app/BackgroundInstallControlServiceTestApp/AndroidManifest.xml index 1fa1f84cd04e..cbe58a8fec70 100644 --- a/services/tests/BackgroundInstallControlServiceTests/host/test-app/BackgroundInstallControlServiceTestApp/AndroidManifest.xml +++ b/services/tests/BackgroundInstallControlServiceTests/host/test-app/BackgroundInstallControlServiceTestApp/AndroidManifest.xml @@ -24,4 +24,4 @@ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner" android:label="APCT tests for background install control service" android:targetPackage="com.android.server.pm.test.app" /> -</manifest> +</manifest>
\ No newline at end of file diff --git a/services/tests/BackgroundInstallControlServiceTests/host/test-app/BackgroundInstallControlServiceTestApp/src/com/android/server/pm/test/app/BackgroundInstallControlServiceTest.java b/services/tests/BackgroundInstallControlServiceTests/host/test-app/BackgroundInstallControlServiceTestApp/src/com/android/server/pm/test/app/BackgroundInstallControlServiceTest.java index b74e5619fd0c..b23f59106881 100644 --- a/services/tests/BackgroundInstallControlServiceTests/host/test-app/BackgroundInstallControlServiceTestApp/src/com/android/server/pm/test/app/BackgroundInstallControlServiceTest.java +++ b/services/tests/BackgroundInstallControlServiceTests/host/test-app/BackgroundInstallControlServiceTestApp/src/com/android/server/pm/test/app/BackgroundInstallControlServiceTest.java @@ -16,6 +16,10 @@ package com.android.server.pm.test.app; +import static android.Manifest.permission.GET_BACKGROUND_INSTALLED_PACKAGES; + +import static com.android.compatibility.common.util.SystemUtil.runShellCommand; + import static com.google.common.truth.Truth.assertThat; import android.content.Context; @@ -23,12 +27,15 @@ import android.content.pm.IBackgroundInstallControlService; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.ParceledListSlice; +import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; -import android.os.UserHandle; import androidx.test.runner.AndroidJUnit4; +import com.android.compatibility.common.util.ShellIdentityUtils; + +import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -39,31 +46,52 @@ import java.util.stream.Collectors; @RunWith(AndroidJUnit4.class) public class BackgroundInstallControlServiceTest { private static final String TAG = "BackgroundInstallControlServiceTest"; + private static final String MOCK_PACKAGE_NAME = "com.android.servicestests.apps.bicmockapp3"; private IBackgroundInstallControlService mIBics; @Before public void setUp() { - mIBics = IBackgroundInstallControlService.Stub.asInterface( - ServiceManager.getService(Context.BACKGROUND_INSTALL_CONTROL_SERVICE)); + mIBics = + IBackgroundInstallControlService.Stub.asInterface( + ServiceManager.getService(Context.BACKGROUND_INSTALL_CONTROL_SERVICE)); assertThat(mIBics).isNotNull(); } + @After + public void tearDown() { + runShellCommand("pm uninstall " + MOCK_PACKAGE_NAME); + } + @Test public void testGetMockBackgroundInstalledPackages() throws RemoteException { - ParceledListSlice<PackageInfo> slice = mIBics.getBackgroundInstalledPackages( - PackageManager.MATCH_ALL, - UserHandle.USER_ALL); + ParceledListSlice<PackageInfo> slice = + ShellIdentityUtils.invokeMethodWithShellPermissions( + mIBics, + (bics) -> { + try { + return bics.getBackgroundInstalledPackages( + PackageManager.MATCH_ALL, Process.myUserHandle() + .getIdentifier()); + } catch (RemoteException e) { + throw new RuntimeException(e); + } + }, + GET_BACKGROUND_INSTALLED_PACKAGES); assertThat(slice).isNotNull(); var packageList = slice.getList(); assertThat(packageList).isNotNull(); assertThat(packageList).hasSize(2); - var expectedPackageNames = Set.of("com.android.servicestests.apps.bicmockapp1", - "com.android.servicestests.apps.bicmockapp2"); - var actualPackageNames = packageList.stream().map((packageInfo) -> packageInfo.packageName) - .collect(Collectors.toSet()); + var expectedPackageNames = + Set.of( + "com.android.servicestests.apps.bicmockapp1", + "com.android.servicestests.apps.bicmockapp2"); + var actualPackageNames = + packageList.stream() + .map((packageInfo) -> packageInfo.packageName) + .collect(Collectors.toSet()); assertThat(actualPackageNames).containsExactlyElementsIn(expectedPackageNames); } -} +}
\ No newline at end of file diff --git a/services/tests/servicestests/src/com/android/server/inputmethod/AdditionalSubtypeUtilsTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/AdditionalSubtypeUtilsTest.java index d82e6abeb502..0edb3dfc0bc0 100644 --- a/services/tests/servicestests/src/com/android/server/inputmethod/AdditionalSubtypeUtilsTest.java +++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/AdditionalSubtypeUtilsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 The Android Open Source Project + * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,18 +26,13 @@ import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodSubtype; import androidx.test.InstrumentationRegistry; -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.Test; -import org.junit.runner.RunWith; import java.io.File; import java.util.List; -@SmallTest -@RunWith(AndroidJUnit4.class) -public class AdditionalSubtypeUtilsTest { +public final class AdditionalSubtypeUtilsTest { @Test public void testSaveAndLoad() throws Exception { @@ -60,7 +55,7 @@ public class AdditionalSubtypeUtilsTest { // Save & load. AtomicFile atomicFile = new AtomicFile( new File(InstrumentationRegistry.getContext().getCacheDir(), "subtypes.xml")); - AdditionalSubtypeUtils.saveToFile(allSubtypes, methodMap, atomicFile); + AdditionalSubtypeUtils.saveToFile(allSubtypes, InputMethodMap.of(methodMap), atomicFile); ArrayMap<String, List<InputMethodSubtype>> loadedSubtypes = new ArrayMap<>(); AdditionalSubtypeUtils.loadFromFile(loadedSubtypes, atomicFile); diff --git a/services/tests/servicestests/src/com/android/server/inputmethod/HardwareKeyboardShortcutControllerTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/HardwareKeyboardShortcutControllerTest.java index 6eedeea8c333..b7223d6615b9 100644 --- a/services/tests/servicestests/src/com/android/server/inputmethod/HardwareKeyboardShortcutControllerTest.java +++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/HardwareKeyboardShortcutControllerTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023 The Android Open Source Project + * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,17 +19,11 @@ package com.android.server.inputmethod; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - import org.junit.Test; -import org.junit.runner.RunWith; import java.util.Arrays; import java.util.List; -@SmallTest -@RunWith(AndroidJUnit4.class) public final class HardwareKeyboardShortcutControllerTest { @Test diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceRestrictImeAmountTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceRestrictImeAmountTest.java index 7cbfc52c5cce..71752ba3b393 100644 --- a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceRestrictImeAmountTest.java +++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceRestrictImeAmountTest.java @@ -28,6 +28,7 @@ import android.content.pm.ResolveInfo; import android.util.ArrayMap; import android.view.inputmethod.InputMethod; import android.view.inputmethod.InputMethodInfo; +import android.view.inputmethod.InputMethodSubtype; import androidx.test.ext.junit.runners.AndroidJUnit4; @@ -123,11 +124,11 @@ public class InputMethodManagerServiceRestrictImeAmountTest extends private List<InputMethodInfo> filterInputMethodServices(List<ResolveInfo> resolveInfoList, List<String> enabledComponents) { - final ArrayMap<String, InputMethodInfo> methodMap = new ArrayMap<>(); - final ArrayList<InputMethodInfo> methodList = new ArrayList<>(); - InputMethodManagerService.filterInputMethodServices(new ArrayMap<>(), methodMap, methodList, - enabledComponents, mContext, resolveInfoList); - return methodList; + final ArrayMap<String, List<InputMethodSubtype>> emptyAdditionalSubtypeMap = + new ArrayMap<>(); + final InputMethodMap methodMap = InputMethodManagerService.filterInputMethodServices( + emptyAdditionalSubtypeMap, enabledComponents, mContext, resolveInfoList); + return methodMap.values(); } private ResolveInfo createFakeSystemResolveInfo(String packageName, String componentName) { diff --git a/services/tests/servicestests/src/com/android/server/inputmethod/InputMethodSubtypeSwitchingControllerTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodSubtypeSwitchingControllerTest.java index 0884b784ac73..fbe384a62658 100644 --- a/services/tests/servicestests/src/com/android/server/inputmethod/InputMethodSubtypeSwitchingControllerTest.java +++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodSubtypeSwitchingControllerTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 The Android Open Source Project + * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,22 +28,16 @@ import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodSubtype; import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder; -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - import com.android.server.inputmethod.InputMethodSubtypeSwitchingController.ControllerImpl; import com.android.server.inputmethod.InputMethodSubtypeSwitchingController.ImeSubtypeListItem; import org.junit.Test; -import org.junit.runner.RunWith; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -@SmallTest -@RunWith(AndroidJUnit4.class) -public class InputMethodSubtypeSwitchingControllerTest { +public final class InputMethodSubtypeSwitchingControllerTest { private static final String DUMMY_PACKAGE_NAME = "dummy package name"; private static final String DUMMY_IME_LABEL = "dummy ime label"; private static final String DUMMY_SETTING_ACTIVITY_NAME = ""; diff --git a/services/tests/servicestests/src/com/android/server/inputmethod/InputMethodUtilsTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodUtilsTest.java index 9688ef6cc83b..2857619c70d3 100644 --- a/services/tests/servicestests/src/com/android/server/inputmethod/InputMethodUtilsTest.java +++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodUtilsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 The Android Open Source Project + * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -41,15 +41,12 @@ import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder; import androidx.annotation.NonNull; import androidx.test.InstrumentationRegistry; -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import com.android.internal.inputmethod.StartInputFlags; import com.google.common.truth.Truth; import org.junit.Test; -import org.junit.runner.RunWith; import java.util.ArrayList; import java.util.Collections; @@ -57,9 +54,7 @@ import java.util.List; import java.util.Locale; import java.util.Objects; -@SmallTest -@RunWith(AndroidJUnit4.class) -public class InputMethodUtilsTest { +public final class InputMethodUtilsTest { private static final boolean IS_AUX = true; private static final boolean IS_DEFAULT = true; private static final boolean IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE = true; @@ -274,7 +269,7 @@ public class InputMethodUtilsTest { "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = - SubtypeUtils.getImplicitlyApplicableSubtypesLocked( + SubtypeUtils.getImplicitlyApplicableSubtypes( new LocaleList(LOCALE_EN_US), imi); assertEquals(1, result.size()); verifyEquality(autoSubtype, result.get(0)); @@ -298,7 +293,7 @@ public class InputMethodUtilsTest { "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = - SubtypeUtils.getImplicitlyApplicableSubtypesLocked( + SubtypeUtils.getImplicitlyApplicableSubtypes( new LocaleList(LOCALE_EN_US), imi); assertEquals(2, result.size()); verifyEquality(nonAutoEnUS, result.get(0)); @@ -322,7 +317,7 @@ public class InputMethodUtilsTest { "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = - SubtypeUtils.getImplicitlyApplicableSubtypesLocked( + SubtypeUtils.getImplicitlyApplicableSubtypes( new LocaleList(LOCALE_EN_GB), imi); assertEquals(2, result.size()); verifyEquality(nonAutoEnGB, result.get(0)); @@ -347,7 +342,7 @@ public class InputMethodUtilsTest { "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = - SubtypeUtils.getImplicitlyApplicableSubtypesLocked( + SubtypeUtils.getImplicitlyApplicableSubtypes( new LocaleList(LOCALE_FR), imi); assertEquals(2, result.size()); verifyEquality(nonAutoFrCA, result.get(0)); @@ -368,7 +363,7 @@ public class InputMethodUtilsTest { "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = - SubtypeUtils.getImplicitlyApplicableSubtypesLocked( + SubtypeUtils.getImplicitlyApplicableSubtypes( new LocaleList(LOCALE_FR_CA), imi); assertEquals(2, result.size()); verifyEquality(nonAutoFrCA, result.get(0)); @@ -390,7 +385,7 @@ public class InputMethodUtilsTest { "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = - SubtypeUtils.getImplicitlyApplicableSubtypesLocked( + SubtypeUtils.getImplicitlyApplicableSubtypes( new LocaleList(LOCALE_JA_JP), imi); assertEquals(3, result.size()); verifyEquality(nonAutoJa, result.get(0)); @@ -412,7 +407,7 @@ public class InputMethodUtilsTest { "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = - SubtypeUtils.getImplicitlyApplicableSubtypesLocked( + SubtypeUtils.getImplicitlyApplicableSubtypes( new LocaleList(LOCALE_JA_JP), imi); assertEquals(1, result.size()); verifyEquality(nonAutoHi, result.get(0)); @@ -429,7 +424,7 @@ public class InputMethodUtilsTest { "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = - SubtypeUtils.getImplicitlyApplicableSubtypesLocked( + SubtypeUtils.getImplicitlyApplicableSubtypes( new LocaleList(LOCALE_JA_JP), imi); assertEquals(1, result.size()); verifyEquality(nonAutoEnUS, result.get(0)); @@ -446,7 +441,7 @@ public class InputMethodUtilsTest { "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = - SubtypeUtils.getImplicitlyApplicableSubtypesLocked( + SubtypeUtils.getImplicitlyApplicableSubtypes( new LocaleList(LOCALE_JA_JP), imi); assertEquals(1, result.size()); verifyEquality(nonAutoEnUS, result.get(0)); @@ -468,7 +463,7 @@ public class InputMethodUtilsTest { "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = - SubtypeUtils.getImplicitlyApplicableSubtypesLocked( + SubtypeUtils.getImplicitlyApplicableSubtypes( new LocaleList(Locale.forLanguageTag("sr-Latn-RS")), imi); assertEquals(2, result.size()); assertThat(nonAutoSrLatn, is(in(result))); @@ -488,7 +483,7 @@ public class InputMethodUtilsTest { "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = - SubtypeUtils.getImplicitlyApplicableSubtypesLocked( + SubtypeUtils.getImplicitlyApplicableSubtypes( new LocaleList(Locale.forLanguageTag("sr-Cyrl-RS")), imi); assertEquals(2, result.size()); assertThat(nonAutoSrCyrl, is(in(result))); @@ -514,7 +509,7 @@ public class InputMethodUtilsTest { "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = - SubtypeUtils.getImplicitlyApplicableSubtypesLocked( + SubtypeUtils.getImplicitlyApplicableSubtypes( new LocaleList( Locale.forLanguageTag("sr-Latn-RS-x-android"), Locale.forLanguageTag("ja-JP"), @@ -541,7 +536,7 @@ public class InputMethodUtilsTest { "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = - SubtypeUtils.getImplicitlyApplicableSubtypesLocked( + SubtypeUtils.getImplicitlyApplicableSubtypes( new LocaleList(LOCALE_FIL_PH), imi); assertEquals(1, result.size()); verifyEquality(nonAutoFil, result.get(0)); @@ -559,7 +554,7 @@ public class InputMethodUtilsTest { "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = - SubtypeUtils.getImplicitlyApplicableSubtypesLocked( + SubtypeUtils.getImplicitlyApplicableSubtypes( new LocaleList(LOCALE_FI), imi); assertEquals(1, result.size()); verifyEquality(nonAutoJa, result.get(0)); @@ -575,7 +570,7 @@ public class InputMethodUtilsTest { "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = - SubtypeUtils.getImplicitlyApplicableSubtypesLocked( + SubtypeUtils.getImplicitlyApplicableSubtypes( new LocaleList(LOCALE_IN), imi); assertEquals(1, result.size()); verifyEquality(nonAutoIn, result.get(0)); @@ -589,7 +584,7 @@ public class InputMethodUtilsTest { "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = - SubtypeUtils.getImplicitlyApplicableSubtypesLocked( + SubtypeUtils.getImplicitlyApplicableSubtypes( new LocaleList(LOCALE_ID), imi); assertEquals(1, result.size()); verifyEquality(nonAutoIn, result.get(0)); @@ -603,7 +598,7 @@ public class InputMethodUtilsTest { "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = - SubtypeUtils.getImplicitlyApplicableSubtypesLocked( + SubtypeUtils.getImplicitlyApplicableSubtypes( new LocaleList(LOCALE_IN), imi); assertEquals(1, result.size()); verifyEquality(nonAutoId, result.get(0)); @@ -617,7 +612,7 @@ public class InputMethodUtilsTest { "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = - SubtypeUtils.getImplicitlyApplicableSubtypesLocked( + SubtypeUtils.getImplicitlyApplicableSubtypes( new LocaleList(LOCALE_ID), imi); assertEquals(1, result.size()); verifyEquality(nonAutoId, result.get(0)); @@ -639,7 +634,7 @@ public class InputMethodUtilsTest { "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT, subtypes); final ArrayList<InputMethodSubtype> result = - SubtypeUtils.getImplicitlyApplicableSubtypesLocked( + SubtypeUtils.getImplicitlyApplicableSubtypes( new LocaleList(LOCALE_FR, LOCALE_EN_US, LOCALE_JA_JP), imi); assertThat(nonAutoFrCA, is(in(result))); assertThat(nonAutoEnUS, is(in(result))); @@ -801,19 +796,22 @@ public class InputMethodUtilsTest { { final ArrayMap<String, InputMethodInfo> methodMap = new ArrayMap<>(); methodMap.put(systemIme.getId(), systemIme); - assertNull(InputMethodInfoUtils.chooseSystemVoiceIme(methodMap, null, "")); + assertNull(InputMethodInfoUtils.chooseSystemVoiceIme(InputMethodMap.of(methodMap), + null, "")); } // Returns null when the config value is empty. { final ArrayMap<String, InputMethodInfo> methodMap = new ArrayMap<>(); methodMap.put(systemIme.getId(), systemIme); - assertNull(InputMethodInfoUtils.chooseSystemVoiceIme(methodMap, "", "")); + assertNull(InputMethodInfoUtils.chooseSystemVoiceIme(InputMethodMap.of(methodMap), "", + "")); } // Returns null when the configured package doesn't have an IME. { - assertNull(InputMethodInfoUtils.chooseSystemVoiceIme(new ArrayMap<>(), + assertNull(InputMethodInfoUtils.chooseSystemVoiceIme( + InputMethodMap.emptyMap(), systemIme.getPackageName(), "")); } @@ -821,7 +819,8 @@ public class InputMethodUtilsTest { { final ArrayMap<String, InputMethodInfo> methodMap = new ArrayMap<>(); methodMap.put(systemIme.getId(), systemIme); - assertEquals(systemIme, InputMethodInfoUtils.chooseSystemVoiceIme(methodMap, + assertEquals(systemIme, InputMethodInfoUtils.chooseSystemVoiceIme( + InputMethodMap.of(methodMap), systemIme.getPackageName(), null)); } @@ -829,13 +828,15 @@ public class InputMethodUtilsTest { { final ArrayMap<String, InputMethodInfo> methodMap = new ArrayMap<>(); methodMap.put(systemIme.getId(), systemIme); - assertEquals(systemIme, InputMethodInfoUtils.chooseSystemVoiceIme(methodMap, + assertEquals(systemIme, InputMethodInfoUtils.chooseSystemVoiceIme( + InputMethodMap.of(methodMap), systemIme.getPackageName(), "")); } // Returns null when the current default isn't found. { - assertNull(InputMethodInfoUtils.chooseSystemVoiceIme(new ArrayMap<>(), + assertNull(InputMethodInfoUtils.chooseSystemVoiceIme( + InputMethodMap.emptyMap(), systemIme.getPackageName(), systemIme.getId())); } @@ -846,7 +847,7 @@ public class InputMethodUtilsTest { final ArrayMap<String, InputMethodInfo> methodMap = new ArrayMap<>(); methodMap.put(systemIme.getId(), systemIme); methodMap.put(secondIme.getId(), secondIme); - assertNull(InputMethodInfoUtils.chooseSystemVoiceIme(methodMap, + assertNull(InputMethodInfoUtils.chooseSystemVoiceIme(InputMethodMap.of(methodMap), systemIme.getPackageName(), "")); } @@ -857,7 +858,8 @@ public class InputMethodUtilsTest { final ArrayMap<String, InputMethodInfo> methodMap = new ArrayMap<>(); methodMap.put(systemIme.getId(), systemIme); methodMap.put(secondIme.getId(), secondIme); - assertEquals(systemIme, InputMethodInfoUtils.chooseSystemVoiceIme(methodMap, + assertEquals(systemIme, InputMethodInfoUtils.chooseSystemVoiceIme( + InputMethodMap.of(methodMap), systemIme.getPackageName(), systemIme.getId())); } @@ -867,7 +869,7 @@ public class InputMethodUtilsTest { final InputMethodInfo nonSystemIme = createFakeInputMethodInfo("NonSystemIme", "fake.voice0", false /* isSystem */); methodMap.put(nonSystemIme.getId(), nonSystemIme); - assertNull(InputMethodInfoUtils.chooseSystemVoiceIme(methodMap, + assertNull(InputMethodInfoUtils.chooseSystemVoiceIme(InputMethodMap.of(methodMap), nonSystemIme.getPackageName(), nonSystemIme.getId())); } @@ -878,7 +880,7 @@ public class InputMethodUtilsTest { "FakeDefaultAutoVoiceIme", "fake.voice0", false /* isSystem */); methodMap.put(systemIme.getId(), systemIme); methodMap.put(nonSystemIme.getId(), nonSystemIme); - assertNull(InputMethodInfoUtils.chooseSystemVoiceIme(methodMap, + assertNull(InputMethodInfoUtils.chooseSystemVoiceIme(InputMethodMap.of(methodMap), nonSystemIme.getPackageName(), "")); } } diff --git a/services/tests/servicestests/src/com/android/server/inputmethod/LocaleUtilsTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/LocaleUtilsTest.java index 255cb6499d8a..d0b46f58d626 100644 --- a/services/tests/servicestests/src/com/android/server/inputmethod/LocaleUtilsTest.java +++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/LocaleUtilsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 The Android Open Source Project + * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,18 +22,12 @@ import static org.junit.Assert.assertEquals; import android.os.LocaleList; -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - import org.junit.Test; -import org.junit.runner.RunWith; import java.util.ArrayList; import java.util.Locale; -@SmallTest -@RunWith(AndroidJUnit4.class) -public class LocaleUtilsTest { +public final class LocaleUtilsTest { private static final LocaleUtils.LocaleExtractor<Locale> sIdentityMapper = source -> source; @@ -392,6 +386,6 @@ public class LocaleUtilsTest { @Test public void testGetLanguageFromLocaleString() { assertThat(LocaleUtils.getLanguageFromLocaleString("en")).isEqualTo("en"); - assertThat(LocaleUtils.getLanguageFromLocaleString("en-US")).isEqualTo("en"); + assertThat(LocaleUtils.getLanguageFromLocaleString("en_US")).isEqualTo("en"); } } diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageUserStateTest.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageUserStateTest.java index 978044045ab3..a185ad99a8f3 100644 --- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageUserStateTest.java +++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageUserStateTest.java @@ -419,7 +419,7 @@ public class PackageUserStateTest { "installerTitle"); packageUserState.setArchiveState(archiveState); assertEquals(archiveState, packageUserState.getArchiveState()); - assertTrue(archiveState.getArchiveTimeMillis() > currentTimeMillis); + assertTrue(archiveState.getArchiveTimeMillis() >= currentTimeMillis); } @Test diff --git a/services/tests/displayservicetests/src/com/android/server/display/mode/DisplayModeDirectorTest.java b/services/tests/displayservicetests/src/com/android/server/display/mode/DisplayModeDirectorTest.java index dd8c6a23b829..c556aca1313a 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/mode/DisplayModeDirectorTest.java +++ b/services/tests/displayservicetests/src/com/android/server/display/mode/DisplayModeDirectorTest.java @@ -1699,6 +1699,37 @@ public class DisplayModeDirectorTest { } @Test + @Parameters({ + "true, true, 60", + "false, true, 50", + "true, false, 50" + }) + public void testExternalDisplayMaxRefreshRate(boolean isRefreshRateSynchronizationEnabled, + boolean isExternalDisplay, float expectedMaxRenderFrameRate) { + when(mDisplayManagerFlags.isDisplaysRefreshRatesSynchronizationEnabled()) + .thenReturn(isRefreshRateSynchronizationEnabled); + when(mResources.getBoolean(R.bool.config_refreshRateSynchronizationEnabled)) + .thenReturn(isRefreshRateSynchronizationEnabled); + mInjector.mDisplayInfo.type = + isExternalDisplay ? Display.TYPE_EXTERNAL : Display.TYPE_INTERNAL; + mInjector.mDisplayInfo.displayId = DISPLAY_ID_2; + + DisplayModeDirector director = createDirectorFromModeArray(TEST_MODES, DEFAULT_MODE_60); + + SparseArray<Vote> votes = new SparseArray<>(); + votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRenderFrameRates(0, 50f)); + + SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>(); + votesByDisplay.put(DISPLAY_ID_2, votes); + + director.getDisplayObserver().onDisplayAdded(DISPLAY_ID_2); + director.injectVotesByDisplay(votesByDisplay); + + var desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID_2); + assertThat(desiredSpecs.primary.render.max).isEqualTo(expectedMaxRenderFrameRate); + } + + @Test public void testMinRefreshRate_FlagEnabled() { when(mDisplayManagerFlags.isBackUpSmoothDisplayAndForcePeakRefreshRateEnabled()) .thenReturn(true); diff --git a/services/tests/mockingservicestests/src/com/android/server/backup/SystemBackupAgentTest.java b/services/tests/mockingservicestests/src/com/android/server/backup/SystemBackupAgentTest.java index 4095be74d294..18dc114a8cd1 100644 --- a/services/tests/mockingservicestests/src/com/android/server/backup/SystemBackupAgentTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/backup/SystemBackupAgentTest.java @@ -20,11 +20,13 @@ import static com.google.common.truth.Truth.assertThat; import android.annotation.NonNull; import android.app.backup.BackupHelper; +import android.app.backup.BackupHelperWithLogger; import android.content.Context; import android.content.pm.PackageManager; import android.os.UserHandle; import android.os.UserManager; import android.platform.test.annotations.Presubmit; +import android.platform.test.flag.junit.SetFlagsRule; import android.util.ArraySet; import static org.mockito.Mockito.when; @@ -32,7 +34,10 @@ import static org.mockito.Mockito.when; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; +import com.android.server.backup.Flags; + import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; @@ -55,6 +60,9 @@ public class SystemBackupAgentTest { @Mock private PackageManager mPackageManagerMock; + @Rule + public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); + @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); @@ -71,7 +79,7 @@ public class SystemBackupAgentTest { mSystemBackupAgent.onCreate(userHandle, /* backupDestination= */ 0); - assertThat(mSystemBackupAgent.mAddedHelpers) + assertThat(mSystemBackupAgent.mAddedHelpersKey) .containsExactly( "account_sync_settings", "preferred_activities", @@ -96,7 +104,7 @@ public class SystemBackupAgentTest { mSystemBackupAgent.onCreate(userHandle, /* backupDestination= */ 0); - assertThat(mSystemBackupAgent.mAddedHelpers) + assertThat(mSystemBackupAgent.mAddedHelpersKey) .containsExactly( "account_sync_settings", "preferred_activities", @@ -118,7 +126,7 @@ public class SystemBackupAgentTest { mSystemBackupAgent.onCreate(userHandle, /* backupDestination= */ 0); - assertThat(mSystemBackupAgent.mAddedHelpers) + assertThat(mSystemBackupAgent.mAddedHelpersKey) .containsExactly( "account_sync_settings", "notifications", @@ -134,7 +142,7 @@ public class SystemBackupAgentTest { mSystemBackupAgent.onCreate(userHandle, /* backupDestination= */ 0); - assertThat(mSystemBackupAgent.mAddedHelpers) + assertThat(mSystemBackupAgent.mAddedHelpersKey) .containsExactly( "account_sync_settings", "preferred_activities", @@ -147,12 +155,42 @@ public class SystemBackupAgentTest { "companion"); } + @Test + public void onAddHelperIfEligibleForUser_flagIsOff_helpersHaveNoLogger() { + UserHandle userHandle = new UserHandle(UserHandle.USER_SYSTEM); + when(mUserManagerMock.isProfile()).thenReturn(false); + mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_METRICS_SYSTEM_BACKUP_AGENTS); + + mSystemBackupAgent.onCreate(userHandle, /* backupDestination= */ 0); + + for (BackupHelperWithLogger helper:mSystemBackupAgent.mAddedHelpers){ + assertThat(helper.isLoggerSet()).isFalse(); + } + } + + @Test + public void onAddHelperIfEligibleForUser_flagIsOn_helpersHaveLogger() { + UserHandle userHandle = new UserHandle(UserHandle.USER_SYSTEM); + when(mUserManagerMock.isProfile()).thenReturn(false); + mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_METRICS_SYSTEM_BACKUP_AGENTS); + + mSystemBackupAgent.onCreate(userHandle, /* backupDestination= */ 0); + + for (BackupHelperWithLogger helper:mSystemBackupAgent.mAddedHelpers){ + assertThat(helper.isLoggerSet()).isTrue(); + } + } + private class TestableSystemBackupAgent extends SystemBackupAgent { - final Set<String> mAddedHelpers = new ArraySet<>(); + final Set<String> mAddedHelpersKey = new ArraySet<>(); + final Set<BackupHelperWithLogger> mAddedHelpers = new ArraySet<>(); @Override public void addHelper(String keyPrefix, BackupHelper helper) { - mAddedHelpers.add(keyPrefix); + mAddedHelpersKey.add(keyPrefix); + if (helper instanceof BackupHelperWithLogger) { + mAddedHelpers.add((BackupHelperWithLogger) helper); + } } @Override diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/FlexibilityControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/FlexibilityControllerTest.java index 284e491f8081..93a2eefba5b1 100644 --- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/FlexibilityControllerTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/FlexibilityControllerTest.java @@ -31,13 +31,17 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; import static com.android.server.job.JobSchedulerService.ACTIVE_INDEX; import static com.android.server.job.JobSchedulerService.EXEMPTED_INDEX; +import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock; import static com.android.server.job.controllers.FlexibilityController.FLEXIBLE_CONSTRAINTS; -import static com.android.server.job.controllers.FlexibilityController.FcConfig.DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_MS; +import static com.android.server.job.controllers.FlexibilityController.FcConfig.DEFAULT_FALLBACK_FLEXIBILITY_DEADLINES; import static com.android.server.job.controllers.FlexibilityController.FcConfig.DEFAULT_UNSEEN_CONSTRAINT_GRACE_PERIOD_MS; import static com.android.server.job.controllers.FlexibilityController.FcConfig.KEY_APPLIED_CONSTRAINTS; import static com.android.server.job.controllers.FlexibilityController.FcConfig.KEY_DEADLINE_PROXIMITY_LIMIT; import static com.android.server.job.controllers.FlexibilityController.FcConfig.KEY_FALLBACK_FLEXIBILITY_DEADLINE; -import static com.android.server.job.controllers.FlexibilityController.FcConfig.KEY_PERCENTS_TO_DROP_NUM_FLEXIBLE_CONSTRAINTS; +import static com.android.server.job.controllers.FlexibilityController.FcConfig.KEY_FALLBACK_FLEXIBILITY_DEADLINES; +import static com.android.server.job.controllers.FlexibilityController.FcConfig.KEY_FALLBACK_FLEXIBILITY_DEADLINE_ADDITIONAL_SCORE_TIME_FACTORS; +import static com.android.server.job.controllers.FlexibilityController.FcConfig.KEY_FALLBACK_FLEXIBILITY_DEADLINE_SCORES; +import static com.android.server.job.controllers.FlexibilityController.FcConfig.KEY_PERCENTS_TO_DROP_FLEXIBLE_CONSTRAINTS; import static com.android.server.job.controllers.FlexibilityController.SYSTEM_WIDE_FLEXIBLE_CONSTRAINTS; import static com.android.server.job.controllers.JobStatus.CONSTRAINT_BATTERY_NOT_LOW; import static com.android.server.job.controllers.JobStatus.CONSTRAINT_CHARGING; @@ -76,6 +80,7 @@ import android.os.PowerManager; import android.provider.DeviceConfig; import android.util.ArraySet; import android.util.EmptyArray; +import android.util.SparseArray; import com.android.server.AppSchedulingModuleThread; import com.android.server.DeviceIdleInternal; @@ -96,6 +101,7 @@ import org.mockito.quality.Strictness; import org.mockito.stubbing.Answer; import java.time.Clock; +import java.time.Duration; import java.time.Instant; import java.time.ZoneOffset; import java.util.ArrayList; @@ -182,7 +188,12 @@ public class FlexibilityControllerTest { mSourceUid = AppGlobals.getPackageManager().getPackageUid(SOURCE_PACKAGE, 0, 0); - setDeviceConfigString(KEY_PERCENTS_TO_DROP_NUM_FLEXIBLE_CONSTRAINTS, "50,60,70,80"); + setDeviceConfigString(KEY_PERCENTS_TO_DROP_FLEXIBLE_CONSTRAINTS, + "500=50|60|70|80" + + ",400=50|60|70|80" + + ",300=50|60|70|80" + + ",200=50|60|70|80" + + ",100=50|60|70|80"); setDeviceConfigLong(KEY_DEADLINE_PROXIMITY_LIMIT, 0L); setDeviceConfigInt(KEY_APPLIED_CONSTRAINTS, FLEXIBLE_CONSTRAINTS); waitForQuietModuleThread(); @@ -200,6 +211,11 @@ public class FlexibilityControllerTest { } } + private void advanceElapsedClock(long incrementMs) { + JobSchedulerService.sElapsedRealtimeClock = Clock.offset( + sElapsedRealtimeClock, Duration.ofMillis(incrementMs)); + } + private void setDeviceConfigInt(String key, int val) { mDeviceConfigPropertiesBuilder.setInt(key, val); updateDeviceConfig(key); @@ -250,9 +266,12 @@ public class FlexibilityControllerTest { */ @Test public void testDefaultVariableValues() { - assertEquals(Integer.bitCount(FLEXIBLE_CONSTRAINTS), - mFlexibilityController.mFcConfig.DEFAULT_PERCENT_TO_DROP_FLEXIBLE_CONSTRAINTS.length - ); + SparseArray<int[]> defaultPercentsToDrop = + FlexibilityController.FcConfig.DEFAULT_PERCENTS_TO_DROP_FLEXIBLE_CONSTRAINTS; + for (int i = 0; i < defaultPercentsToDrop.size(); ++i) { + assertEquals(Integer.bitCount(FLEXIBLE_CONSTRAINTS), + defaultPercentsToDrop.valueAt(i).length); + } } @Test @@ -379,10 +398,13 @@ public class FlexibilityControllerTest { @Test public void testOnConstantsUpdated_FallbackDeadline() { JobStatus js = createJobStatus("testFallbackDeadlineConfig", createJob(0)); - assertEquals(DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_MS, - mFlexibilityController.getLifeCycleEndElapsedLocked(js, 0L)); - setDeviceConfigLong(KEY_FALLBACK_FLEXIBILITY_DEADLINE, 100L); - assertEquals(100L, mFlexibilityController.getLifeCycleEndElapsedLocked(js, 0L)); + final long nowElapsed = sElapsedRealtimeClock.millis(); + assertEquals(DEFAULT_FALLBACK_FLEXIBILITY_DEADLINES.get(JobInfo.PRIORITY_DEFAULT), + mFlexibilityController.getLifeCycleEndElapsedLocked(js, nowElapsed, 0L)); + setDeviceConfigLong(KEY_FALLBACK_FLEXIBILITY_DEADLINE, 123L); + setDeviceConfigString(KEY_FALLBACK_FLEXIBILITY_DEADLINES, + "500=500,400=400,300=300,200=200,100=100"); + assertEquals(300L, mFlexibilityController.getLifeCycleEndElapsedLocked(js, nowElapsed, 0L)); } @Test @@ -392,10 +414,32 @@ public class FlexibilityControllerTest { JobStatus js = createJobStatus("testPercentsToDropConstraintsConfig", jb); assertEquals(FROZEN_TIME + MIN_WINDOW_FOR_FLEXIBILITY_MS / 10 * 5, mFlexibilityController.getNextConstraintDropTimeElapsedLocked(js)); - setDeviceConfigString(KEY_PERCENTS_TO_DROP_NUM_FLEXIBLE_CONSTRAINTS, "10,20,30,40"); + setDeviceConfigString(KEY_PERCENTS_TO_DROP_FLEXIBLE_CONSTRAINTS, + "500=1|2|3|4" + + ",400=5|6|7|8" + + ",300=10|20|30|40" + + ",200=50|51|52|53" + + ",100=54|55|56|57"); + assertArrayEquals( + mFlexibilityController.mFcConfig.PERCENTS_TO_DROP_FLEXIBLE_CONSTRAINTS + .get(JobInfo.PRIORITY_MAX), + new int[]{1, 2, 3, 4}); + assertArrayEquals( + mFlexibilityController.mFcConfig.PERCENTS_TO_DROP_FLEXIBLE_CONSTRAINTS + .get(JobInfo.PRIORITY_HIGH), + new int[]{5, 6, 7, 8}); + assertArrayEquals( + mFlexibilityController.mFcConfig.PERCENTS_TO_DROP_FLEXIBLE_CONSTRAINTS + .get(JobInfo.PRIORITY_DEFAULT), + new int[]{10, 20, 30, 40}); assertArrayEquals( - mFlexibilityController.mFcConfig.PERCENTS_TO_DROP_NUM_FLEXIBLE_CONSTRAINTS, - new int[] {10, 20, 30, 40}); + mFlexibilityController.mFcConfig.PERCENTS_TO_DROP_FLEXIBLE_CONSTRAINTS + .get(JobInfo.PRIORITY_LOW), + new int[]{50, 51, 52, 53}); + assertArrayEquals( + mFlexibilityController.mFcConfig.PERCENTS_TO_DROP_FLEXIBLE_CONSTRAINTS + .get(JobInfo.PRIORITY_MIN), + new int[]{54, 55, 56, 57}); assertEquals(FROZEN_TIME + MIN_WINDOW_FOR_FLEXIBILITY_MS / 10, mFlexibilityController.getNextConstraintDropTimeElapsedLocked(js)); js.setNumDroppedFlexibleConstraints(1); @@ -408,25 +452,64 @@ public class FlexibilityControllerTest { @Test public void testOnConstantsUpdated_PercentsToDropConstraintsInvalidValues() { - JobInfo.Builder jb = createJob(0).setOverrideDeadline(HOUR_IN_MILLIS); - JobStatus js = createJobStatus("testPercentsToDropConstraintsConfig", jb); - js.enqueueTime = JobSchedulerService.sElapsedRealtimeClock.millis(); - assertEquals(js.enqueueTime + HOUR_IN_MILLIS / 2, - mFlexibilityController.getNextConstraintDropTimeElapsedLocked(js)); - setDeviceConfigString(KEY_PERCENTS_TO_DROP_NUM_FLEXIBLE_CONSTRAINTS, "10,20a,030,40"); - assertEquals(js.enqueueTime + HOUR_IN_MILLIS / 2, - mFlexibilityController.getNextConstraintDropTimeElapsedLocked(js)); - setDeviceConfigString(KEY_PERCENTS_TO_DROP_NUM_FLEXIBLE_CONSTRAINTS, "10,40"); - assertEquals(js.enqueueTime + HOUR_IN_MILLIS / 2, - mFlexibilityController.getNextConstraintDropTimeElapsedLocked(js)); - setDeviceConfigString(KEY_PERCENTS_TO_DROP_NUM_FLEXIBLE_CONSTRAINTS, "50,40,10,40"); - assertEquals(js.enqueueTime + HOUR_IN_MILLIS / 2, - mFlexibilityController.getNextConstraintDropTimeElapsedLocked(js)); + // No priority mapping + setDeviceConfigString(KEY_PERCENTS_TO_DROP_FLEXIBLE_CONSTRAINTS, "10,20,30,40"); + final SparseArray<int[]> defaultPercentsToDrop = + FlexibilityController.FcConfig.DEFAULT_PERCENTS_TO_DROP_FLEXIBLE_CONSTRAINTS; + final SparseArray<int[]> percentsToDrop = + mFlexibilityController.mFcConfig.PERCENTS_TO_DROP_FLEXIBLE_CONSTRAINTS; + for (int i = 0; i < defaultPercentsToDrop.size(); ++i) { + assertArrayEquals(defaultPercentsToDrop.valueAt(i), percentsToDrop.valueAt(i)); + } + + // Invalid priority-percentList string + setDeviceConfigString(KEY_PERCENTS_TO_DROP_FLEXIBLE_CONSTRAINTS, + "500=10,20a,030,40" + + ",400=20|40|60|80" + + ",300=25|50|75|80" + + ",200=40|50|60|80" + + ",100=20|40|60|80"); + for (int i = 0; i < defaultPercentsToDrop.size(); ++i) { + assertArrayEquals(defaultPercentsToDrop.valueAt(i), percentsToDrop.valueAt(i)); + } + + // Invalid percentList strings + setDeviceConfigString(KEY_PERCENTS_TO_DROP_FLEXIBLE_CONSTRAINTS, + "500=10|20a|030|40" // Letters + + ",400=10|40" // Not enough + + ",300=.|50|_|80" // Characters + + ",200=50|40|10|40" // Out of order + + ",100=30|60|90|101"); // Over 100 + for (int i = 0; i < defaultPercentsToDrop.size(); ++i) { + assertArrayEquals(defaultPercentsToDrop.valueAt(i), percentsToDrop.valueAt(i)); + } + + // Only partially invalid + setDeviceConfigString(KEY_PERCENTS_TO_DROP_FLEXIBLE_CONSTRAINTS, + "500=10|20a|030|40" // Letters + + ",400=10|40" // Not enough + + ",300=.|50|_|80" // Characters + + ",200=10|20|30|40" // Valid + + ",100=20|40|60|80"); // Valid + assertArrayEquals(defaultPercentsToDrop.get(JobInfo.PRIORITY_MAX), + percentsToDrop.get(JobInfo.PRIORITY_MAX)); + assertArrayEquals(defaultPercentsToDrop.get(JobInfo.PRIORITY_HIGH), + percentsToDrop.get(JobInfo.PRIORITY_HIGH)); + assertArrayEquals(defaultPercentsToDrop.get(JobInfo.PRIORITY_DEFAULT), + percentsToDrop.get(JobInfo.PRIORITY_DEFAULT)); + assertArrayEquals(new int[]{10, 20, 30, 40}, percentsToDrop.get(JobInfo.PRIORITY_LOW)); + assertArrayEquals(new int[]{20, 40, 60, 80}, percentsToDrop.get(JobInfo.PRIORITY_MIN)); } @Test public void testGetNextConstraintDropTimeElapsedLocked() { setDeviceConfigLong(KEY_FALLBACK_FLEXIBILITY_DEADLINE, 200 * HOUR_IN_MILLIS); + setDeviceConfigString(KEY_FALLBACK_FLEXIBILITY_DEADLINES, + "500=" + HOUR_IN_MILLIS + + ",400=" + 25 * HOUR_IN_MILLIS + + ",300=" + 50 * HOUR_IN_MILLIS + + ",200=" + 100 * HOUR_IN_MILLIS + + ",100=" + 200 * HOUR_IN_MILLIS); long nextTimeToDropNumConstraints; @@ -459,34 +542,34 @@ public class FlexibilityControllerTest { nextTimeToDropNumConstraints = mFlexibilityController .getNextConstraintDropTimeElapsedLocked(js); - assertEquals(FROZEN_TIME + 800000L + (200 * HOUR_IN_MILLIS) / 2, + assertEquals(FROZEN_TIME + 800000L + (50 * HOUR_IN_MILLIS) / 2, nextTimeToDropNumConstraints); js.setNumDroppedFlexibleConstraints(1); nextTimeToDropNumConstraints = mFlexibilityController .getNextConstraintDropTimeElapsedLocked(js); - assertEquals(FROZEN_TIME + 800000L + (200 * HOUR_IN_MILLIS) * 6 / 10, + assertEquals(FROZEN_TIME + 800000L + (50 * HOUR_IN_MILLIS) * 6 / 10, nextTimeToDropNumConstraints); js.setNumDroppedFlexibleConstraints(2); nextTimeToDropNumConstraints = mFlexibilityController .getNextConstraintDropTimeElapsedLocked(js); - assertEquals(FROZEN_TIME + 800000L + (200 * HOUR_IN_MILLIS) * 7 / 10, + assertEquals(FROZEN_TIME + 800000L + (50 * HOUR_IN_MILLIS) * 7 / 10, nextTimeToDropNumConstraints); // no delay, no deadline - jb = createJob(0); + jb = createJob(0).setPriority(JobInfo.PRIORITY_LOW); js = createJobStatus("time", jb); nextTimeToDropNumConstraints = mFlexibilityController .getNextConstraintDropTimeElapsedLocked(js); - assertEquals(FROZEN_TIME + (200 * HOUR_IN_MILLIS) / 2, nextTimeToDropNumConstraints); + assertEquals(FROZEN_TIME + (100 * HOUR_IN_MILLIS) / 2, nextTimeToDropNumConstraints); js.setNumDroppedFlexibleConstraints(1); nextTimeToDropNumConstraints = mFlexibilityController .getNextConstraintDropTimeElapsedLocked(js); - assertEquals(FROZEN_TIME + (200 * HOUR_IN_MILLIS) * 6 / 10, nextTimeToDropNumConstraints); + assertEquals(FROZEN_TIME + (100 * HOUR_IN_MILLIS) * 6 / 10, nextTimeToDropNumConstraints); js.setNumDroppedFlexibleConstraints(2); nextTimeToDropNumConstraints = mFlexibilityController .getNextConstraintDropTimeElapsedLocked(js); - assertEquals(FROZEN_TIME + (200 * HOUR_IN_MILLIS) * 7 / 10, nextTimeToDropNumConstraints); + assertEquals(FROZEN_TIME + (100 * HOUR_IN_MILLIS) * 7 / 10, nextTimeToDropNumConstraints); // delay, deadline jb = createJob(0) @@ -514,13 +597,13 @@ public class FlexibilityControllerTest { @Test public void testCurPercent() { long deadline = 100 * MINUTE_IN_MILLIS; - long nowElapsed; + long nowElapsed = FROZEN_TIME; JobInfo.Builder jb = createJob(0).setOverrideDeadline(deadline); JobStatus js = createJobStatus("time", jb); assertEquals(FROZEN_TIME, mFlexibilityController.getLifeCycleBeginningElapsedLocked(js)); assertEquals(deadline + FROZEN_TIME, - mFlexibilityController.getLifeCycleEndElapsedLocked(js, FROZEN_TIME)); + mFlexibilityController.getLifeCycleEndElapsedLocked(js, nowElapsed, FROZEN_TIME)); nowElapsed = FROZEN_TIME + 60 * MINUTE_IN_MILLIS; JobSchedulerService.sElapsedRealtimeClock = Clock.fixed(Instant.ofEpochMilli(nowElapsed), ZoneOffset.UTC); @@ -547,7 +630,8 @@ public class FlexibilityControllerTest { assertEquals(FROZEN_TIME + delay, mFlexibilityController.getLifeCycleBeginningElapsedLocked(js)); assertEquals(deadline + FROZEN_TIME, - mFlexibilityController.getLifeCycleEndElapsedLocked(js, FROZEN_TIME + delay)); + mFlexibilityController.getLifeCycleEndElapsedLocked(js, nowElapsed, + FROZEN_TIME + delay)); nowElapsed = FROZEN_TIME + delay + 60 * MINUTE_IN_MILLIS; JobSchedulerService.sElapsedRealtimeClock = @@ -670,34 +754,63 @@ public class FlexibilityControllerTest { @Test public void testGetLifeCycleEndElapsedLocked_Prefetch() { + final long nowElapsed = sElapsedRealtimeClock.millis(); + // prefetch no estimate JobInfo.Builder jb = createJob(0).setPrefetch(true); JobStatus js = createJobStatus("time", jb); doReturn(Long.MAX_VALUE).when(mPrefetchController).getNextEstimatedLaunchTimeLocked(js); - assertEquals(Long.MAX_VALUE, mFlexibilityController.getLifeCycleEndElapsedLocked(js, 0)); + assertEquals(Long.MAX_VALUE, + mFlexibilityController.getLifeCycleEndElapsedLocked(js, nowElapsed, 0)); + // prefetch with estimate jb = createJob(0).setPrefetch(true); js = createJobStatus("time", jb); doReturn(1000L).when(mPrefetchController).getNextEstimatedLaunchTimeLocked(js); - assertEquals(1000L, mFlexibilityController.getLifeCycleEndElapsedLocked(js, 0)); + assertEquals(1000L, + mFlexibilityController.getLifeCycleEndElapsedLocked(js, nowElapsed, 0)); } @Test public void testGetLifeCycleEndElapsedLocked_NonPrefetch() { + setDeviceConfigString(KEY_FALLBACK_FLEXIBILITY_DEADLINES, + "500=" + HOUR_IN_MILLIS + + ",400=" + 2 * HOUR_IN_MILLIS + + ",300=" + 3 * HOUR_IN_MILLIS + + ",200=" + 4 * HOUR_IN_MILLIS + + ",100=" + 5 * HOUR_IN_MILLIS); + + final long nowElapsed = sElapsedRealtimeClock.millis(); + // deadline JobInfo.Builder jb = createJob(0).setOverrideDeadline(HOUR_IN_MILLIS); JobStatus js = createJobStatus("time", jb); assertEquals(HOUR_IN_MILLIS + FROZEN_TIME, - mFlexibilityController.getLifeCycleEndElapsedLocked(js, 0)); + mFlexibilityController.getLifeCycleEndElapsedLocked(js, nowElapsed, 0)); + // no deadline - jb = createJob(0); - js = createJobStatus("time", jb); - assertEquals(FROZEN_TIME + DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_MS, - mFlexibilityController.getLifeCycleEndElapsedLocked(js, 100L)); + assertEquals(FROZEN_TIME + 2 * HOUR_IN_MILLIS, + mFlexibilityController.getLifeCycleEndElapsedLocked( + createJobStatus("time", createJob(0).setPriority(JobInfo.PRIORITY_HIGH)), + nowElapsed, 100L)); + assertEquals(FROZEN_TIME + 3 * HOUR_IN_MILLIS, + mFlexibilityController.getLifeCycleEndElapsedLocked( + createJobStatus("time", createJob(0).setPriority(JobInfo.PRIORITY_DEFAULT)), + nowElapsed, 100L)); + assertEquals(FROZEN_TIME + 4 * HOUR_IN_MILLIS, + mFlexibilityController.getLifeCycleEndElapsedLocked( + createJobStatus("time", createJob(0).setPriority(JobInfo.PRIORITY_LOW)), + nowElapsed, 100L)); + assertEquals(FROZEN_TIME + 5 * HOUR_IN_MILLIS, + mFlexibilityController.getLifeCycleEndElapsedLocked( + createJobStatus("time", createJob(0).setPriority(JobInfo.PRIORITY_MIN)), + nowElapsed, 100L)); } @Test public void testGetLifeCycleEndElapsedLocked_Rescheduled() { + final long nowElapsed = sElapsedRealtimeClock.millis(); + JobInfo.Builder jb = createJob(0).setOverrideDeadline(HOUR_IN_MILLIS); JobStatus js = createJobStatus("time", jb); js = new JobStatus( @@ -705,20 +818,91 @@ public class FlexibilityControllerTest { 0, FROZEN_TIME, FROZEN_TIME); assertEquals(mFcConfig.RESCHEDULED_JOB_DEADLINE_MS, - mFlexibilityController.getLifeCycleEndElapsedLocked(js, 0)); + mFlexibilityController.getLifeCycleEndElapsedLocked(js, nowElapsed, 0)); js = new JobStatus( js, FROZEN_TIME, NO_LATEST_RUNTIME, /* numFailures */ 2, /* numSystemStops */ 1, 0, FROZEN_TIME, FROZEN_TIME); assertEquals(2 * mFcConfig.RESCHEDULED_JOB_DEADLINE_MS, - mFlexibilityController.getLifeCycleEndElapsedLocked(js, 0)); + mFlexibilityController.getLifeCycleEndElapsedLocked(js, nowElapsed, 0)); js = new JobStatus( js, FROZEN_TIME, NO_LATEST_RUNTIME, /* numFailures */ 0, /* numSystemStops */ 10, 0, FROZEN_TIME, FROZEN_TIME); assertEquals(mFcConfig.MAX_RESCHEDULED_DEADLINE_MS, - mFlexibilityController.getLifeCycleEndElapsedLocked(js, 0)); + mFlexibilityController.getLifeCycleEndElapsedLocked(js, nowElapsed, 0)); + } + + @Test + public void testGetLifeCycleEndElapsedLocked_ScoreAddition() { + setDeviceConfigString(KEY_FALLBACK_FLEXIBILITY_DEADLINES, + "500=" + HOUR_IN_MILLIS + + ",400=" + HOUR_IN_MILLIS + + ",300=" + HOUR_IN_MILLIS + + ",200=" + HOUR_IN_MILLIS + + ",100=" + HOUR_IN_MILLIS); + setDeviceConfigString(KEY_FALLBACK_FLEXIBILITY_DEADLINE_SCORES, + "500=5,400=4,300=3,200=2,100=1"); + setDeviceConfigString(KEY_FALLBACK_FLEXIBILITY_DEADLINE_ADDITIONAL_SCORE_TIME_FACTORS, + "500=" + 5 * MINUTE_IN_MILLIS + + ",400=" + 4 * MINUTE_IN_MILLIS + + ",300=" + 3 * MINUTE_IN_MILLIS + + ",200=" + 2 * MINUTE_IN_MILLIS + + ",100=" + 1 * MINUTE_IN_MILLIS); + + final long nowElapsed = sElapsedRealtimeClock.millis(); + + JobStatus jsMax = createJobStatus("testScoreCalculation", + createJob(0).setExpedited(true).setPriority(JobInfo.PRIORITY_MAX)); + JobStatus jsHigh = createJobStatus("testScoreCalculation", + createJob(0).setPriority(JobInfo.PRIORITY_HIGH)); + JobStatus jsDefault = createJobStatus("testScoreCalculation", + createJob(0).setPriority(JobInfo.PRIORITY_DEFAULT)); + JobStatus jsLow = createJobStatus("testScoreCalculation", + createJob(0).setPriority(JobInfo.PRIORITY_LOW)); + JobStatus jsMin = createJobStatus("testScoreCalculation", + createJob(0).setPriority(JobInfo.PRIORITY_MIN)); + // Make score = 15 + mFlexibilityController.prepareForExecutionLocked(jsMax); + mFlexibilityController.prepareForExecutionLocked(jsHigh); + mFlexibilityController.prepareForExecutionLocked(jsDefault); + mFlexibilityController.prepareForExecutionLocked(jsLow); + mFlexibilityController.prepareForExecutionLocked(jsMin); + + // deadline + JobInfo.Builder jb = createJob(0).setOverrideDeadline(HOUR_IN_MILLIS); + JobStatus js = createJobStatus("testGetLifeCycleEndElapsedLocked_ScoreAddition", jb); + assertEquals(HOUR_IN_MILLIS + FROZEN_TIME, + mFlexibilityController.getLifeCycleEndElapsedLocked(js, nowElapsed, 0)); + + final long earliestMs = 123L; + // no deadline + assertEquals(earliestMs + HOUR_IN_MILLIS + 5 * 15 * MINUTE_IN_MILLIS, + mFlexibilityController.getLifeCycleEndElapsedLocked( + createJobStatus("testGetLifeCycleEndElapsedLocked_ScoreAddition", + createJob(0).setExpedited(true).setPriority(JobInfo.PRIORITY_MAX)), + nowElapsed, earliestMs)); + assertEquals(earliestMs + HOUR_IN_MILLIS + 4 * 15 * MINUTE_IN_MILLIS, + mFlexibilityController.getLifeCycleEndElapsedLocked( + createJobStatus("testGetLifeCycleEndElapsedLocked_ScoreAddition", + createJob(0).setPriority(JobInfo.PRIORITY_HIGH)), + nowElapsed, earliestMs)); + assertEquals(earliestMs + HOUR_IN_MILLIS + 3 * 15 * MINUTE_IN_MILLIS, + mFlexibilityController.getLifeCycleEndElapsedLocked( + createJobStatus("testGetLifeCycleEndElapsedLocked_ScoreAddition", + createJob(0).setPriority(JobInfo.PRIORITY_DEFAULT)), + nowElapsed, earliestMs)); + assertEquals(earliestMs + HOUR_IN_MILLIS + 2 * 15 * MINUTE_IN_MILLIS, + mFlexibilityController.getLifeCycleEndElapsedLocked( + createJobStatus("testGetLifeCycleEndElapsedLocked_ScoreAddition", + createJob(0).setPriority(JobInfo.PRIORITY_LOW)), + nowElapsed, earliestMs)); + assertEquals(earliestMs + HOUR_IN_MILLIS + 1 * 15 * MINUTE_IN_MILLIS, + mFlexibilityController.getLifeCycleEndElapsedLocked( + createJobStatus("testGetLifeCycleEndElapsedLocked_ScoreAddition", + createJob(0).setPriority(JobInfo.PRIORITY_MIN)), + nowElapsed, earliestMs)); } @Test @@ -734,6 +918,14 @@ public class FlexibilityControllerTest { @Test public void testFlexibilityTracker() { + setDeviceConfigLong(KEY_FALLBACK_FLEXIBILITY_DEADLINE, 100 * HOUR_IN_MILLIS); + setDeviceConfigString(KEY_FALLBACK_FLEXIBILITY_DEADLINES, + "500=" + 100 * HOUR_IN_MILLIS + + ",400=" + 100 * HOUR_IN_MILLIS + + ",300=" + 100 * HOUR_IN_MILLIS + + ",200=" + 100 * HOUR_IN_MILLIS + + ",100=" + 100 * HOUR_IN_MILLIS); + FlexibilityController.FlexibilityTracker flexTracker = mFlexibilityController.new FlexibilityTracker(4); // Plus one for jobs with 0 required constraint. @@ -805,8 +997,7 @@ public class FlexibilityControllerTest { assertEquals(1, trackedJobs.get(3).size()); assertEquals(0, trackedJobs.get(4).size()); - final long nowElapsed = ((DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_MS / 2) - + HOUR_IN_MILLIS); + final long nowElapsed = 51 * HOUR_IN_MILLIS; JobSchedulerService.sElapsedRealtimeClock = Clock.fixed(Instant.ofEpochMilli(nowElapsed), ZoneOffset.UTC); @@ -1220,66 +1411,161 @@ public class FlexibilityControllerTest { @Test public void testCalculateNumDroppedConstraints() { - JobInfo.Builder jb = createJob(22); - JobStatus js = createJobStatus("testCalculateNumDroppedConstraints", jb); - long nowElapsed = FROZEN_TIME; - - mFlexibilityController.mFlexibilityTracker.add(js); - - assertEquals(3, js.getNumRequiredFlexibleConstraints()); - assertEquals(0, js.getNumDroppedFlexibleConstraints()); - assertEquals(1, mFlexibilityController + setDeviceConfigString(KEY_FALLBACK_FLEXIBILITY_DEADLINES, + "500=" + HOUR_IN_MILLIS + + ",400=" + 5 * HOUR_IN_MILLIS + + ",300=" + 8 * HOUR_IN_MILLIS + + ",200=" + 10 * HOUR_IN_MILLIS + + ",100=" + 20 * HOUR_IN_MILLIS); + setDeviceConfigString(KEY_PERCENTS_TO_DROP_FLEXIBLE_CONSTRAINTS, + "500=20|40|60|80" + + ",400=20|40|60|80" + + ",300=25|50|75|80" + + ",200=40|50|60|80" + + ",100=20|40|60|80"); + + JobStatus jsHigh = createJobStatus("testCalculateNumDroppedConstraints", + createJob(24).setPriority(JobInfo.PRIORITY_HIGH)); + JobStatus jsDefault = createJobStatus("testCalculateNumDroppedConstraints", + createJob(23).setPriority(JobInfo.PRIORITY_DEFAULT)); + JobStatus jsLow = createJobStatus("testCalculateNumDroppedConstraints", + createJob(22).setPriority(JobInfo.PRIORITY_LOW)); + JobStatus jsMin = createJobStatus("testCalculateNumDroppedConstraints", + createJob(21).setPriority(JobInfo.PRIORITY_MIN)); + final long startElapsed = FROZEN_TIME; + long nowElapsed = startElapsed; + + mFlexibilityController.mFlexibilityTracker.add(jsHigh); + mFlexibilityController.mFlexibilityTracker.add(jsDefault); + mFlexibilityController.mFlexibilityTracker.add(jsLow); + mFlexibilityController.mFlexibilityTracker.add(jsMin); + + assertEquals(3, jsHigh.getNumRequiredFlexibleConstraints()); + assertEquals(0, jsHigh.getNumDroppedFlexibleConstraints()); + assertEquals(3, jsDefault.getNumRequiredFlexibleConstraints()); + assertEquals(0, jsDefault.getNumDroppedFlexibleConstraints()); + assertEquals(3, jsLow.getNumRequiredFlexibleConstraints()); + assertEquals(0, jsLow.getNumDroppedFlexibleConstraints()); + assertEquals(3, jsMin.getNumRequiredFlexibleConstraints()); + assertEquals(0, jsMin.getNumDroppedFlexibleConstraints()); + assertEquals(4, mFlexibilityController .mFlexibilityTracker.getJobsByNumRequiredConstraints(3).size()); - nowElapsed += DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_MS / 10 * 5; + nowElapsed = startElapsed + HOUR_IN_MILLIS; JobSchedulerService.sElapsedRealtimeClock = Clock.fixed(Instant.ofEpochMilli(nowElapsed), ZoneOffset.UTC); mFlexibilityController.mFlexibilityTracker - .setNumDroppedFlexibleConstraints(js, 1); - - assertEquals(2, js.getNumRequiredFlexibleConstraints()); - assertEquals(1, js.getNumDroppedFlexibleConstraints()); - assertEquals(1, mFlexibilityController - .mFlexibilityTracker.getJobsByNumRequiredConstraints(2).size()); - - mFlexibilityController.mFlexibilityTracker.calculateNumDroppedConstraints(js, nowElapsed); - - assertEquals(2, js.getNumRequiredFlexibleConstraints()); - assertEquals(1, js.getNumDroppedFlexibleConstraints()); + .calculateNumDroppedConstraints(jsHigh, nowElapsed); + mFlexibilityController.mFlexibilityTracker + .calculateNumDroppedConstraints(jsDefault, nowElapsed); + mFlexibilityController.mFlexibilityTracker + .calculateNumDroppedConstraints(jsLow, nowElapsed); + mFlexibilityController.mFlexibilityTracker + .calculateNumDroppedConstraints(jsMin, nowElapsed); + + assertEquals(2, jsHigh.getNumRequiredFlexibleConstraints()); + assertEquals(1, jsHigh.getNumDroppedFlexibleConstraints()); + assertEquals(3, jsDefault.getNumRequiredFlexibleConstraints()); + assertEquals(0, jsDefault.getNumDroppedFlexibleConstraints()); + assertEquals(3, jsLow.getNumRequiredFlexibleConstraints()); + assertEquals(0, jsLow.getNumDroppedFlexibleConstraints()); + assertEquals(3, jsMin.getNumRequiredFlexibleConstraints()); + assertEquals(0, jsMin.getNumDroppedFlexibleConstraints()); + assertEquals(3, mFlexibilityController + .mFlexibilityTracker.getJobsByNumRequiredConstraints(3).size()); assertEquals(1, mFlexibilityController .mFlexibilityTracker.getJobsByNumRequiredConstraints(2).size()); - nowElapsed = FROZEN_TIME; + nowElapsed = startElapsed; JobSchedulerService.sElapsedRealtimeClock = Clock.fixed(Instant.ofEpochMilli(nowElapsed), ZoneOffset.UTC); - mFlexibilityController.mFlexibilityTracker.calculateNumDroppedConstraints(js, nowElapsed); - - assertEquals(3, js.getNumRequiredFlexibleConstraints()); - assertEquals(0, js.getNumDroppedFlexibleConstraints()); - assertEquals(1, mFlexibilityController + mFlexibilityController.mFlexibilityTracker + .calculateNumDroppedConstraints(jsHigh, nowElapsed); + mFlexibilityController.mFlexibilityTracker + .calculateNumDroppedConstraints(jsDefault, nowElapsed); + mFlexibilityController.mFlexibilityTracker + .calculateNumDroppedConstraints(jsLow, nowElapsed); + mFlexibilityController.mFlexibilityTracker + .calculateNumDroppedConstraints(jsMin, nowElapsed); + + assertEquals(3, jsHigh.getNumRequiredFlexibleConstraints()); + assertEquals(0, jsHigh.getNumDroppedFlexibleConstraints()); + assertEquals(3, jsDefault.getNumRequiredFlexibleConstraints()); + assertEquals(0, jsDefault.getNumDroppedFlexibleConstraints()); + assertEquals(3, jsLow.getNumRequiredFlexibleConstraints()); + assertEquals(0, jsLow.getNumDroppedFlexibleConstraints()); + assertEquals(3, jsMin.getNumRequiredFlexibleConstraints()); + assertEquals(0, jsMin.getNumDroppedFlexibleConstraints()); + assertEquals(4, mFlexibilityController .mFlexibilityTracker.getJobsByNumRequiredConstraints(3).size()); + assertEquals(0, mFlexibilityController + .mFlexibilityTracker.getJobsByNumRequiredConstraints(2).size()); + assertEquals(0, mFlexibilityController + .mFlexibilityTracker.getJobsByNumRequiredConstraints(1).size()); + assertEquals(0, mFlexibilityController + .mFlexibilityTracker.getJobsByNumRequiredConstraints(0).size()); - nowElapsed += DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_MS / 10 * 9; + nowElapsed = startElapsed + 3 * HOUR_IN_MILLIS; JobSchedulerService.sElapsedRealtimeClock = Clock.fixed(Instant.ofEpochMilli(nowElapsed), ZoneOffset.UTC); - mFlexibilityController.mFlexibilityTracker.calculateNumDroppedConstraints(js, nowElapsed); - - assertEquals(0, js.getNumRequiredFlexibleConstraints()); - assertEquals(3, js.getNumDroppedFlexibleConstraints()); + mFlexibilityController.mFlexibilityTracker + .calculateNumDroppedConstraints(jsHigh, nowElapsed); + mFlexibilityController.mFlexibilityTracker + .calculateNumDroppedConstraints(jsDefault, nowElapsed); + mFlexibilityController.mFlexibilityTracker + .calculateNumDroppedConstraints(jsLow, nowElapsed); + mFlexibilityController.mFlexibilityTracker + .calculateNumDroppedConstraints(jsMin, nowElapsed); + + assertEquals(0, jsHigh.getNumRequiredFlexibleConstraints()); + assertEquals(3, jsHigh.getNumDroppedFlexibleConstraints()); + assertEquals(2, jsDefault.getNumRequiredFlexibleConstraints()); + assertEquals(1, jsDefault.getNumDroppedFlexibleConstraints()); + assertEquals(3, jsLow.getNumRequiredFlexibleConstraints()); + assertEquals(0, jsLow.getNumDroppedFlexibleConstraints()); + assertEquals(3, jsMin.getNumRequiredFlexibleConstraints()); + assertEquals(0, jsMin.getNumDroppedFlexibleConstraints()); + assertEquals(2, mFlexibilityController + .mFlexibilityTracker.getJobsByNumRequiredConstraints(3).size()); + assertEquals(1, mFlexibilityController + .mFlexibilityTracker.getJobsByNumRequiredConstraints(2).size()); + assertEquals(0, mFlexibilityController + .mFlexibilityTracker.getJobsByNumRequiredConstraints(1).size()); + assertEquals(1, mFlexibilityController + .mFlexibilityTracker.getJobsByNumRequiredConstraints(0).size()); - nowElapsed = FROZEN_TIME + DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_MS / 10 * 6; + nowElapsed = startElapsed + 4 * HOUR_IN_MILLIS; JobSchedulerService.sElapsedRealtimeClock = Clock.fixed(Instant.ofEpochMilli(nowElapsed), ZoneOffset.UTC); - mFlexibilityController.mFlexibilityTracker.calculateNumDroppedConstraints(js, nowElapsed); - - assertEquals(1, js.getNumRequiredFlexibleConstraints()); - assertEquals(2, js.getNumDroppedFlexibleConstraints()); + mFlexibilityController.mFlexibilityTracker + .calculateNumDroppedConstraints(jsHigh, nowElapsed); + mFlexibilityController.mFlexibilityTracker + .calculateNumDroppedConstraints(jsDefault, nowElapsed); + mFlexibilityController.mFlexibilityTracker + .calculateNumDroppedConstraints(jsLow, nowElapsed); + mFlexibilityController.mFlexibilityTracker + .calculateNumDroppedConstraints(jsMin, nowElapsed); + + assertEquals(0, jsHigh.getNumRequiredFlexibleConstraints()); + assertEquals(3, jsHigh.getNumDroppedFlexibleConstraints()); + assertEquals(1, jsDefault.getNumRequiredFlexibleConstraints()); + assertEquals(2, jsDefault.getNumDroppedFlexibleConstraints()); + assertEquals(2, jsLow.getNumRequiredFlexibleConstraints()); + assertEquals(1, jsLow.getNumDroppedFlexibleConstraints()); + assertEquals(2, jsMin.getNumRequiredFlexibleConstraints()); + assertEquals(1, jsMin.getNumDroppedFlexibleConstraints()); + assertEquals(0, mFlexibilityController + .mFlexibilityTracker.getJobsByNumRequiredConstraints(3).size()); + assertEquals(2, mFlexibilityController + .mFlexibilityTracker.getJobsByNumRequiredConstraints(2).size()); assertEquals(1, mFlexibilityController .mFlexibilityTracker.getJobsByNumRequiredConstraints(1).size()); + assertEquals(1, mFlexibilityController + .mFlexibilityTracker.getJobsByNumRequiredConstraints(0).size()); } @Test @@ -1308,7 +1594,7 @@ public class FlexibilityControllerTest { .get(js.getSourceUserId(), js.getSourcePackageName())); assertEquals(150L, mFlexibilityController.getLifeCycleBeginningElapsedLocked(js)); assertEquals(1150L, - mFlexibilityController.getLifeCycleEndElapsedLocked(js, 150L)); + mFlexibilityController.getLifeCycleEndElapsedLocked(js, nowElapsed, 150L)); assertEquals(0, mFlexibilityController.getCurPercentOfLifecycleLocked(js, FROZEN_TIME)); assertEquals(650L, mFlexibilityController .getNextConstraintDropTimeElapsedLocked(js)); @@ -1317,6 +1603,80 @@ public class FlexibilityControllerTest { .mFlexibilityTracker.getJobsByNumRequiredConstraints(3).size()); } + @Test + public void testScoreCalculation() { + JobStatus jsMax = createJobStatus("testScoreCalculation", + createJob(0).setExpedited(true).setPriority(JobInfo.PRIORITY_MAX)); + JobStatus jsHigh = createJobStatus("testScoreCalculation", + createJob(0).setPriority(JobInfo.PRIORITY_HIGH)); + JobStatus jsDefault = createJobStatus("testScoreCalculation", + createJob(0).setPriority(JobInfo.PRIORITY_DEFAULT)); + JobStatus jsLow = createJobStatus("testScoreCalculation", + createJob(0).setPriority(JobInfo.PRIORITY_LOW)); + JobStatus jsMin = createJobStatus("testScoreCalculation", + createJob(0).setPriority(JobInfo.PRIORITY_MIN)); + + long nowElapsed = sElapsedRealtimeClock.millis(); + assertEquals(0, + mFlexibilityController.getScoreLocked(mSourceUid, SOURCE_PACKAGE, nowElapsed)); + + mFlexibilityController.prepareForExecutionLocked(jsMax); + assertEquals(5, + mFlexibilityController.getScoreLocked(mSourceUid, SOURCE_PACKAGE, nowElapsed)); + + advanceElapsedClock(30 * MINUTE_IN_MILLIS); + nowElapsed += 30 * MINUTE_IN_MILLIS; + mFlexibilityController.prepareForExecutionLocked(jsMax); + assertEquals(10, + mFlexibilityController.getScoreLocked(mSourceUid, SOURCE_PACKAGE, nowElapsed)); + + advanceElapsedClock(31 * MINUTE_IN_MILLIS); + nowElapsed += 31 * MINUTE_IN_MILLIS; + mFlexibilityController.prepareForExecutionLocked(jsHigh); + assertEquals(14, + mFlexibilityController.getScoreLocked(mSourceUid, SOURCE_PACKAGE, nowElapsed)); + + advanceElapsedClock(2 * HOUR_IN_MILLIS); + nowElapsed += 2 * HOUR_IN_MILLIS; + mFlexibilityController.prepareForExecutionLocked(jsDefault); + assertEquals(17, + mFlexibilityController.getScoreLocked(mSourceUid, SOURCE_PACKAGE, nowElapsed)); + + advanceElapsedClock(3 * HOUR_IN_MILLIS); + nowElapsed += 3 * HOUR_IN_MILLIS; + mFlexibilityController.prepareForExecutionLocked(jsLow); + assertEquals(19, + mFlexibilityController.getScoreLocked(mSourceUid, SOURCE_PACKAGE, nowElapsed)); + + advanceElapsedClock(3 * HOUR_IN_MILLIS); + nowElapsed += 3 * HOUR_IN_MILLIS; + mFlexibilityController.prepareForExecutionLocked(jsMin); + assertEquals(20, + mFlexibilityController.getScoreLocked(mSourceUid, SOURCE_PACKAGE, nowElapsed)); + + advanceElapsedClock(3 * HOUR_IN_MILLIS); + nowElapsed += 3 * HOUR_IN_MILLIS; + mFlexibilityController.prepareForExecutionLocked(jsMax); + assertEquals(25, + mFlexibilityController.getScoreLocked(mSourceUid, SOURCE_PACKAGE, nowElapsed)); + mFlexibilityController.unprepareFromExecutionLocked(jsMax); + assertEquals(20, + mFlexibilityController.getScoreLocked(mSourceUid, SOURCE_PACKAGE, nowElapsed)); + + // 24 hours haven't passed yet. The jobs in the first hour bucket should still be included. + advanceElapsedClock(12 * HOUR_IN_MILLIS - MINUTE_IN_MILLIS - 1); + nowElapsed += 12 * HOUR_IN_MILLIS - MINUTE_IN_MILLIS - 1; + assertEquals(20, + mFlexibilityController.getScoreLocked(mSourceUid, SOURCE_PACKAGE, nowElapsed)); + + // Passed the 24 hour mark. The jobs in the first hour bucket should no longer be included. + advanceElapsedClock(2); + nowElapsed += 2; + assertEquals(10, + mFlexibilityController.getScoreLocked(mSourceUid, SOURCE_PACKAGE, nowElapsed)); + + } + /** * The beginning of a lifecycle for prefetch jobs includes the cached maximum of the last time * the estimated launch time was updated and the last time the app was opened. diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/PackageArchiverTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/PackageArchiverTest.java index ec7e35982311..a65ef00f8a21 100644 --- a/services/tests/mockingservicestests/src/com/android/server/pm/PackageArchiverTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/pm/PackageArchiverTest.java @@ -367,7 +367,7 @@ public class PackageArchiverTest { verify(mInstallerService).uninstall( eq(new VersionedPackage(PACKAGE, PackageManager.VERSION_CODE_HIGHEST)), eq(CALLER_PACKAGE), eq(DELETE_ARCHIVE | DELETE_KEEP_DATA), eq(mIntentSender), - eq(UserHandle.CURRENT.getIdentifier()), anyInt()); + eq(UserHandle.CURRENT.getIdentifier()), anyInt(), anyInt()); ArchiveState expectedArchiveState = createArchiveState(); ArchiveState actualArchiveState = mPackageSetting.readUserState( @@ -391,7 +391,7 @@ public class PackageArchiverTest { eq(CALLER_PACKAGE), eq(DELETE_ARCHIVE | DELETE_KEEP_DATA), eq(mIntentSender), - eq(UserHandle.CURRENT.getIdentifier()), anyInt()); + eq(UserHandle.CURRENT.getIdentifier()), anyInt(), anyInt()); ArchiveState expectedArchiveState = createArchiveState(); ArchiveState actualArchiveState = mPackageSetting.readUserState( diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java index e6298eeccafb..5bec903e6414 100644 --- a/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/pm/UserManagerServiceTest.java @@ -569,6 +569,23 @@ public final class UserManagerServiceTest { } @Test + public void testAutoLockPrivateProfile() { + UserManagerService mSpiedUms = spy(mUms); + UserInfo privateProfileUser = + mSpiedUms.createProfileForUserEvenWhenDisallowedWithThrow("TestPrivateProfile", + USER_TYPE_PROFILE_PRIVATE, 0, 0, null); + Mockito.doNothing().when(mSpiedUms).setQuietModeEnabledAsync( + eq(privateProfileUser.getUserHandle().getIdentifier()), eq(true), any(), + any()); + + mSpiedUms.autoLockPrivateSpace(); + + Mockito.verify(mSpiedUms).setQuietModeEnabledAsync( + eq(privateProfileUser.getUserHandle().getIdentifier()), eq(true), + any(), any()); + } + + @Test public void testAutoLockOnDeviceLockForPrivateProfile() { mSetFlagsRule.enableFlags(Flags.FLAG_SUPPORT_AUTOLOCK_FOR_PRIVATE_SPACE); UserManagerService mSpiedUms = spy(mUms); 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 57c3a1d5f364..95cfc2a304d4 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java @@ -22,6 +22,7 @@ import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_ import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_NONE; import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW; import static android.view.accessibility.Flags.FLAG_CLEANUP_ACCESSIBILITY_WARNING_DIALOG; +import static android.view.accessibility.Flags.FLAG_SKIP_ACCESSIBILITY_WARNING_DIALOG_FOR_TRUSTED_SERVICES; import static com.android.internal.accessibility.AccessibilityShortcutController.ACCESSIBILITY_HEARING_AIDS_COMPONENT_NAME; import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_CONTROLLER_NAME; @@ -82,6 +83,7 @@ import androidx.test.core.app.ApplicationProvider; import androidx.test.filters.SmallTest; import com.android.compatibility.common.util.TestUtils; +import com.android.internal.R; import com.android.internal.compat.IPlatformCompat; import com.android.server.LocalServices; import com.android.server.accessibility.AccessibilityManagerService.AccessibilityDisplayListener; @@ -857,8 +859,7 @@ public class AccessibilityManagerServiceTest { @RequiresFlagsEnabled(FLAG_CLEANUP_ACCESSIBILITY_WARNING_DIALOG) public void testIsAccessibilityServiceWarningRequired_requiredByDefault() { mockManageAccessibilityGranted(mTestableContext); - final AccessibilityServiceInfo info = new AccessibilityServiceInfo(); - info.setComponentName(COMPONENT_NAME); + final AccessibilityServiceInfo info = mockAccessibilityServiceInfo(COMPONENT_NAME); assertThat(mA11yms.isAccessibilityServiceWarningRequired(info)).isTrue(); } @@ -867,10 +868,9 @@ public class AccessibilityManagerServiceTest { @RequiresFlagsEnabled(FLAG_CLEANUP_ACCESSIBILITY_WARNING_DIALOG) public void testIsAccessibilityServiceWarningRequired_notRequiredIfAlreadyEnabled() { mockManageAccessibilityGranted(mTestableContext); - final AccessibilityServiceInfo info_a = new AccessibilityServiceInfo(); - info_a.setComponentName(COMPONENT_NAME); - final AccessibilityServiceInfo info_b = new AccessibilityServiceInfo(); - info_b.setComponentName(new ComponentName("package_b", "class_b")); + final AccessibilityServiceInfo info_a = mockAccessibilityServiceInfo(COMPONENT_NAME); + final AccessibilityServiceInfo info_b = mockAccessibilityServiceInfo( + new ComponentName("package_b", "class_b")); final AccessibilityUserState userState = mA11yms.getCurrentUserState(); userState.mEnabledServices.clear(); userState.mEnabledServices.add(info_b.getComponentName()); @@ -883,12 +883,12 @@ public class AccessibilityManagerServiceTest { @RequiresFlagsEnabled(FLAG_CLEANUP_ACCESSIBILITY_WARNING_DIALOG) public void testIsAccessibilityServiceWarningRequired_notRequiredIfExistingShortcut() { mockManageAccessibilityGranted(mTestableContext); - final AccessibilityServiceInfo info_a = new AccessibilityServiceInfo(); - info_a.setComponentName(new ComponentName("package_a", "class_a")); - final AccessibilityServiceInfo info_b = new AccessibilityServiceInfo(); - info_b.setComponentName(new ComponentName("package_b", "class_b")); - final AccessibilityServiceInfo info_c = new AccessibilityServiceInfo(); - info_c.setComponentName(new ComponentName("package_c", "class_c")); + final AccessibilityServiceInfo info_a = mockAccessibilityServiceInfo( + new ComponentName("package_a", "class_a")); + final AccessibilityServiceInfo info_b = mockAccessibilityServiceInfo( + new ComponentName("package_b", "class_b")); + final AccessibilityServiceInfo info_c = mockAccessibilityServiceInfo( + new ComponentName("package_c", "class_c")); final AccessibilityUserState userState = mA11yms.getCurrentUserState(); userState.mAccessibilityButtonTargets.clear(); userState.mAccessibilityButtonTargets.add(info_b.getComponentName().flattenToString()); @@ -900,6 +900,51 @@ public class AccessibilityManagerServiceTest { assertThat(mA11yms.isAccessibilityServiceWarningRequired(info_c)).isFalse(); } + @Test + @RequiresFlagsEnabled({ + FLAG_CLEANUP_ACCESSIBILITY_WARNING_DIALOG, + FLAG_SKIP_ACCESSIBILITY_WARNING_DIALOG_FOR_TRUSTED_SERVICES}) + public void testIsAccessibilityServiceWarningRequired_notRequiredIfAllowlisted() { + mockManageAccessibilityGranted(mTestableContext); + final AccessibilityServiceInfo info_a = mockAccessibilityServiceInfo( + new ComponentName("package_a", "class_a"), true); + final AccessibilityServiceInfo info_b = mockAccessibilityServiceInfo( + new ComponentName("package_b", "class_b"), false); + final AccessibilityServiceInfo info_c = mockAccessibilityServiceInfo( + new ComponentName("package_c", "class_c"), true); + mTestableContext.getOrCreateTestableResources().addOverride( + R.array.config_trustedAccessibilityServices, + new String[]{ + info_b.getComponentName().flattenToString(), + info_c.getComponentName().flattenToString()}); + + // info_a is not in the allowlist => require the warning + assertThat(mA11yms.isAccessibilityServiceWarningRequired(info_a)).isTrue(); + // info_b is not preinstalled => require the warning + assertThat(mA11yms.isAccessibilityServiceWarningRequired(info_b)).isTrue(); + // info_c is both in the allowlist and preinstalled => do not require the warning + assertThat(mA11yms.isAccessibilityServiceWarningRequired(info_c)).isFalse(); + } + + private static AccessibilityServiceInfo mockAccessibilityServiceInfo( + ComponentName componentName) { + return mockAccessibilityServiceInfo(componentName, false); + } + + private static AccessibilityServiceInfo mockAccessibilityServiceInfo( + ComponentName componentName, + boolean isSystemApp) { + AccessibilityServiceInfo accessibilityServiceInfo = + Mockito.spy(new AccessibilityServiceInfo()); + accessibilityServiceInfo.setComponentName(componentName); + ResolveInfo mockResolveInfo = Mockito.mock(ResolveInfo.class); + when(accessibilityServiceInfo.getResolveInfo()).thenReturn(mockResolveInfo); + mockResolveInfo.serviceInfo = Mockito.mock(ServiceInfo.class); + mockResolveInfo.serviceInfo.applicationInfo = Mockito.mock(ApplicationInfo.class); + when(mockResolveInfo.serviceInfo.applicationInfo.isSystemApp()).thenReturn(isSystemApp); + return accessibilityServiceInfo; + } + // Single package intents can trigger multiple PackageMonitor callbacks. // Collect the state of the lock in a set, since tests only care if calls // were all locked or all unlocked. diff --git a/services/tests/servicestests/src/com/android/server/audio/LoudnessCodecHelperTest.java b/services/tests/servicestests/src/com/android/server/audio/LoudnessCodecHelperTest.java index 9c8276aac4dd..84c0ab38ca48 100644 --- a/services/tests/servicestests/src/com/android/server/audio/LoudnessCodecHelperTest.java +++ b/services/tests/servicestests/src/com/android/server/audio/LoudnessCodecHelperTest.java @@ -15,6 +15,7 @@ */ package com.android.server.audio; +import static android.media.AudioAttributes.ALLOW_CAPTURE_BY_NONE; import static android.media.AudioManager.GET_DEVICES_OUTPUTS; import static android.media.AudioPlaybackConfiguration.PLAYER_UPDATE_DEVICE_ID; import static android.media.LoudnessCodecInfo.CodecMetadataType.CODEC_METADATA_TYPE_MPEG_4; @@ -22,6 +23,7 @@ import static android.media.LoudnessCodecInfo.CodecMetadataType.CODEC_METADATA_T import static android.media.MediaFormat.KEY_AAC_DRC_EFFECT_TYPE; import static android.media.MediaFormat.KEY_AAC_DRC_HEAVY_COMPRESSION; import static android.media.MediaFormat.KEY_AAC_DRC_TARGET_REFERENCE_LEVEL; +import static android.os.Process.myPid; import static com.android.server.audio.LoudnessCodecHelper.SPL_RANGE_LARGE; import static com.android.server.audio.LoudnessCodecHelper.SPL_RANGE_MEDIUM; @@ -37,6 +39,7 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.media.AudioAttributes; import android.media.AudioDeviceInfo; import android.media.AudioManager; import android.media.AudioPlaybackConfiguration; @@ -64,13 +67,16 @@ import org.mockito.junit.MockitoRule; import java.util.ArrayList; import java.util.List; -import java.util.Random; @RunWith(AndroidJUnit4.class) @Presubmit public class LoudnessCodecHelperTest { private static final String TAG = "LoudnessCodecHelperTest"; + private static final int TEST_USAGE = AudioAttributes.USAGE_MEDIA; + + private static final int TEST_CONTENT = AudioAttributes.CONTENT_TYPE_MUSIC; + @Rule public final MockitoRule mockito = MockitoJUnit.rule(); @@ -83,94 +89,84 @@ public class LoudnessCodecHelperTest { private final int mInitialApcPiid = 1; + private int mSessionId; + @Before public void setUp() throws Exception { mLoudnessHelper = new LoudnessCodecHelper(mAudioService); + mSessionId = 1; when(mAudioService.getActivePlaybackConfigurations()).thenReturn( - getApcListForPiids(mInitialApcPiid)); + getApcListForApcWithPiidSid(mInitialApcPiid, mSessionId, 0)); when(mDispatcher.asBinder()).thenReturn(Mockito.mock(IBinder.class)); } @Test - public void registerDispatcher_sendsInitialUpdateOnStart() throws Exception { + public void registerDispatcher_sendsUpdateOnAddCodec() throws Exception { mLoudnessHelper.registerLoudnessCodecUpdatesDispatcher(mDispatcher); - mLoudnessHelper.startLoudnessCodecUpdates(mInitialApcPiid, - List.of(getLoudnessInfo(/*isDownmixing=*/true, CODEC_METADATA_TYPE_MPEG_4))); + mLoudnessHelper.startLoudnessCodecUpdates(mSessionId); + mLoudnessHelper.addLoudnessCodecInfo(mSessionId, /*mediaCodecHash=*/222, + getLoudnessInfo(/*isDownmixing=*/true, CODEC_METADATA_TYPE_MPEG_D)); - verify(mDispatcher).dispatchLoudnessCodecParameterChange(eq(mInitialApcPiid), any()); + verify(mDispatcher).dispatchLoudnessCodecParameterChange(eq(mSessionId), any()); } @Test - public void unregisterDispatcher_noInitialUpdateOnStart() throws Exception { + public void unregisterDispatcher_noUpdateOnAdd() throws Exception { mLoudnessHelper.registerLoudnessCodecUpdatesDispatcher(mDispatcher); mLoudnessHelper.unregisterLoudnessCodecUpdatesDispatcher(mDispatcher); - mLoudnessHelper.startLoudnessCodecUpdates(mInitialApcPiid, - List.of(getLoudnessInfo(/*isDownmixing=*/false, CODEC_METADATA_TYPE_MPEG_D))); + mLoudnessHelper.startLoudnessCodecUpdates(mSessionId); + mLoudnessHelper.addLoudnessCodecInfo(mSessionId, /*mediaCodecHash=*/222, + getLoudnessInfo(/*isDownmixing=*/true, CODEC_METADATA_TYPE_MPEG_D)); - verify(mDispatcher, times(0)).dispatchLoudnessCodecParameterChange(eq(mInitialApcPiid), + verify(mDispatcher, times(0)).dispatchLoudnessCodecParameterChange(eq(mSessionId), any()); } @Test - public void addCodecInfo_sendsInitialUpdateAfterStart() throws Exception { + public void addCodecInfoForDifferentId_noUpdateSent() throws Exception { + final int newSessionId = mSessionId + 1; mLoudnessHelper.registerLoudnessCodecUpdatesDispatcher(mDispatcher); - mLoudnessHelper.startLoudnessCodecUpdates(mInitialApcPiid, - List.of(getLoudnessInfo(/*isDownmixing=*/true, CODEC_METADATA_TYPE_MPEG_4))); - mLoudnessHelper.addLoudnessCodecInfo(mInitialApcPiid, /*mediaCodecHash=*/222, + mLoudnessHelper.startLoudnessCodecUpdates(mSessionId); + mLoudnessHelper.addLoudnessCodecInfo(newSessionId, /*mediaCodecHash=*/222, getLoudnessInfo(/*isDownmixing=*/true, CODEC_METADATA_TYPE_MPEG_D)); - verify(mDispatcher, times(2)).dispatchLoudnessCodecParameterChange(eq(mInitialApcPiid), + verify(mDispatcher, times(0)).dispatchLoudnessCodecParameterChange(eq(mSessionId), any()); } @Test - public void addCodecInfoForUnstartedPiid_noUpdateSent() throws Exception { - final int newPiid = 2; + public void updateCodecParameters_noStartedPiids_noDispatch() throws Exception { mLoudnessHelper.registerLoudnessCodecUpdatesDispatcher(mDispatcher); - - mLoudnessHelper.startLoudnessCodecUpdates(mInitialApcPiid, - List.of(getLoudnessInfo(/*isDownmixing=*/true, - CODEC_METADATA_TYPE_MPEG_4))); - mLoudnessHelper.addLoudnessCodecInfo(newPiid, /*mediaCodecHash=*/222, + mLoudnessHelper.addLoudnessCodecInfo(mSessionId, /*mediaCodecHash=*/222, getLoudnessInfo(/*isDownmixing=*/true, CODEC_METADATA_TYPE_MPEG_D)); - verify(mDispatcher, times(1)).dispatchLoudnessCodecParameterChange(eq(mInitialApcPiid), - any()); - } + mLoudnessHelper.updateCodecParameters( + getApcListForApcWithPiidSid(mInitialApcPiid, mSessionId, 1)); - @Test - public void updateCodecParameters_updatesOnlyStartedPiids() throws Exception { - final int newPiid = 2; - mLoudnessHelper.registerLoudnessCodecUpdatesDispatcher(mDispatcher); - - mLoudnessHelper.startLoudnessCodecUpdates(mInitialApcPiid, - List.of(getLoudnessInfo(/*isDownmixing=*/true, CODEC_METADATA_TYPE_MPEG_4))); - //does not trigger dispatch since active apc list does not contain newPiid - mLoudnessHelper.startLoudnessCodecUpdates(newPiid, - List.of(getLoudnessInfo(/*isDownmixing=*/true, CODEC_METADATA_TYPE_MPEG_D))); - verify(mDispatcher, times(1)).dispatchLoudnessCodecParameterChange(eq(mInitialApcPiid), + // no dispatch since mSessionId was not started + verify(mDispatcher, times(0)).dispatchLoudnessCodecParameterChange(eq(mSessionId), any()); - - // triggers dispatch for new active apc with newPiid - mLoudnessHelper.updateCodecParameters(getApcListForPiids(newPiid)); - verify(mDispatcher, times(1)).dispatchLoudnessCodecParameterChange(eq(newPiid), any()); } @Test - public void updateCodecParameters_noStartedPiids_noDispatch() throws Exception { + public void updateCodecParameters_dispatchUpdates() throws Exception { + final LoudnessCodecInfo info = getLoudnessInfo(/*isDownmixing=*/true, + CODEC_METADATA_TYPE_MPEG_4); mLoudnessHelper.registerLoudnessCodecUpdatesDispatcher(mDispatcher); - mLoudnessHelper.addLoudnessCodecInfo(mInitialApcPiid, /*mediaCodecHash=*/222, - getLoudnessInfo(/*isDownmixing=*/true, CODEC_METADATA_TYPE_MPEG_D)); - mLoudnessHelper.updateCodecParameters(getApcListForPiids(mInitialApcPiid)); + mLoudnessHelper.startLoudnessCodecUpdates(mSessionId); + mLoudnessHelper.addLoudnessCodecInfo(mSessionId, /*mediaCodecHash=*/222, info); - // no dispatch since mInitialApcPiid was not started - verify(mDispatcher, times(0)).dispatchLoudnessCodecParameterChange(eq(mInitialApcPiid), + mLoudnessHelper.updateCodecParameters( + getApcListForApcWithPiidSid(mInitialApcPiid, mSessionId, 1)); + + // second dispatch since player configurations were updated + verify(mDispatcher, times(2)).dispatchLoudnessCodecParameterChange(eq(mSessionId), any()); } @@ -180,13 +176,15 @@ public class LoudnessCodecHelperTest { CODEC_METADATA_TYPE_MPEG_4); mLoudnessHelper.registerLoudnessCodecUpdatesDispatcher(mDispatcher); - mLoudnessHelper.startLoudnessCodecUpdates(mInitialApcPiid, List.of(info)); - mLoudnessHelper.removeLoudnessCodecInfo(mInitialApcPiid, info); + mLoudnessHelper.startLoudnessCodecUpdates(mSessionId); + mLoudnessHelper.addLoudnessCodecInfo(mSessionId, /*mediaCodecHash=*/222, info); + mLoudnessHelper.removeLoudnessCodecInfo(mSessionId, info); - mLoudnessHelper.updateCodecParameters(getApcListForPiids(mInitialApcPiid)); + mLoudnessHelper.updateCodecParameters( + getApcListForApcWithPiidSid(mInitialApcPiid, mSessionId, 1)); // no second dispatch since codec info was removed for updates - verify(mDispatcher, times(1)).dispatchLoudnessCodecParameterChange(eq(mInitialApcPiid), + verify(mDispatcher, times(1)).dispatchLoudnessCodecParameterChange(eq(mSessionId), any()); } @@ -196,13 +194,14 @@ public class LoudnessCodecHelperTest { CODEC_METADATA_TYPE_MPEG_4); mLoudnessHelper.registerLoudnessCodecUpdatesDispatcher(mDispatcher); - mLoudnessHelper.startLoudnessCodecUpdates(mInitialApcPiid, List.of(info)); - mLoudnessHelper.stopLoudnessCodecUpdates(mInitialApcPiid); + mLoudnessHelper.startLoudnessCodecUpdates(mSessionId); + mLoudnessHelper.stopLoudnessCodecUpdates(mSessionId); - mLoudnessHelper.updateCodecParameters(getApcListForPiids(mInitialApcPiid)); + mLoudnessHelper.updateCodecParameters( + getApcListForApcWithPiidSid(mInitialApcPiid, mSessionId, 1)); // no second dispatch since piid was removed for updates - verify(mDispatcher, times(1)).dispatchLoudnessCodecParameterChange(eq(mInitialApcPiid), + verify(mDispatcher, times(0)).dispatchLoudnessCodecParameterChange(eq(mSessionId), any()); } @@ -308,23 +307,28 @@ public class LoudnessCodecHelperTest { assertEquals(6, loudnessParameters.getInt(KEY_AAC_DRC_EFFECT_TYPE)); } - private List<AudioPlaybackConfiguration> getApcListForPiids(int... piids) { + private List<AudioPlaybackConfiguration> getApcListForApcWithPiidSid(int piid, int sessionId, + int devIdx) { final ArrayList<AudioPlaybackConfiguration> apcList = new ArrayList<>(); AudioDeviceInfo[] devicesStatic = AudioManager.getDevicesStatic(GET_DEVICES_OUTPUTS); - assumeTrue(devicesStatic.length > 0); - int index = new Random().nextInt(devicesStatic.length); - Log.d(TAG, "Out devices number " + devicesStatic.length + ". Picking index " + index); - int deviceId = devicesStatic[index].getId(); - - for (int piid : piids) { - PlayerBase.PlayerIdCard idCard = Mockito.mock(PlayerBase.PlayerIdCard.class); - AudioPlaybackConfiguration apc = - new AudioPlaybackConfiguration(idCard, piid, /*uid=*/1, /*pid=*/1); - apc.handleStateEvent(PLAYER_UPDATE_DEVICE_ID, deviceId); - - apcList.add(apc); - } + assumeTrue(devIdx < devicesStatic.length); + Log.d(TAG, "Out devices number " + devicesStatic.length + ". Picking index " + devIdx); + int deviceId = devicesStatic[devIdx].getId(); + + PlayerBase.PlayerIdCard idCard = Mockito.mock(PlayerBase.PlayerIdCard.class); + AudioPlaybackConfiguration apc = + new AudioPlaybackConfiguration(idCard, piid, /*uid=*/1, /*pid=*/myPid()); + apc.handleStateEvent(PLAYER_UPDATE_DEVICE_ID, deviceId); + apc.handleSessionIdEvent(sessionId); + apc.handleAudioAttributesEvent(new AudioAttributes.Builder() + .setUsage(AudioAttributes.USAGE_MEDIA) + .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) + .setAllowedCapturePolicy(ALLOW_CAPTURE_BY_NONE) + .build()); + + apcList.add(apc); + return apcList; } diff --git a/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricContextProviderTest.java b/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricContextProviderTest.java index a8eace05de97..c7300bbb50a7 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricContextProviderTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricContextProviderTest.java @@ -20,6 +20,7 @@ import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS; import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertThrows; import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.mock; @@ -33,11 +34,15 @@ import android.content.Intent; import android.hardware.biometrics.AuthenticateOptions; import android.hardware.biometrics.IBiometricContextListener; import android.hardware.biometrics.IBiometricContextListener.FoldState; +import android.hardware.biometrics.common.DisplayState; import android.hardware.biometrics.common.OperationContext; import android.hardware.biometrics.common.OperationReason; import android.hardware.display.DisplayManagerGlobal; +import android.hardware.fingerprint.FingerprintAuthenticateOptions; import android.os.RemoteException; import android.platform.test.annotations.Presubmit; +import android.platform.test.flag.junit.CheckFlagsRule; +import android.platform.test.flag.junit.DeviceFlagsValueProvider; import android.testing.TestableContext; import android.view.Display; import android.view.DisplayInfo; @@ -72,6 +77,9 @@ public class BiometricContextProviderTest { @Rule public TestableContext mContext = new TestableContext( InstrumentationRegistry.getInstrumentation().getContext()); + @Rule + public final CheckFlagsRule mCheckFlagsRule = + DeviceFlagsValueProvider.createCheckFlagsRule(); @Mock private IStatusBarService mStatusBarService; @@ -395,6 +403,37 @@ public class BiometricContextProviderTest { } } + @Test + public void testSubscribe_thenStartHal() throws RemoteException { + Consumer<OperationContext> updateConsumer = mock(Consumer.class); + Consumer<OperationContext> startHalConsumer = mock(Consumer.class); + AuthenticateOptions options = new FingerprintAuthenticateOptions.Builder().build(); + OperationContextExt context = mProvider.updateContext(mOpContext, false /* crypto */); + + assertThat(context.getDisplayState()).isEqualTo(DisplayState.UNKNOWN); + assertThat(context.getFoldState()).isEqualTo(IBiometricContextListener.FoldState.UNKNOWN); + + mListener.onDisplayStateChanged(DisplayState.LOCKSCREEN); + mListener.onFoldChanged(FoldState.FULLY_CLOSED); + mProvider.subscribe(context, startHalConsumer, updateConsumer, options); + + assertThat(context.getDisplayState()).isEqualTo(DisplayState.LOCKSCREEN); + assertThat(context.getFoldState()).isEqualTo(FoldState.FULLY_CLOSED); + verify(updateConsumer, never()).accept(context.toAidlContext()); + verify(startHalConsumer).accept(context.toAidlContext(options)); + } + + @Test + public void testSubscribe_withInvalidOptions() { + Consumer<OperationContext> updateConsumer = mock(Consumer.class); + Consumer<OperationContext> startHalConsumer = mock(Consumer.class); + AuthenticateOptions options = mock(AuthenticateOptions.class); + OperationContextExt context = mProvider.updateContext(mOpContext, false /* crypto */); + + assertThrows(IllegalStateException.class, () -> mProvider.subscribe( + context, startHalConsumer, updateConsumer, options)); + } + private static byte reason(int type) { if (type == StatusBarManager.SESSION_BIOMETRIC_PROMPT) { return OperationReason.BIOMETRIC_PROMPT; diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java index 0973d46283ed..5e380108aeb3 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java @@ -25,6 +25,7 @@ import static com.android.server.hdmi.Constants.ADDR_RECORDER_1; import static com.android.server.hdmi.Constants.ADDR_TV; import static com.android.server.hdmi.HdmiCecLocalDevice.ActiveSource; import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_ENABLE_CEC; +import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_WAKE_UP_MESSAGE; import static com.google.common.truth.Truth.assertThat; @@ -1807,4 +1808,35 @@ public class HdmiCecLocalDeviceTvTest { // TV should only send <Give Osd Name> once assertEquals(1, Collections.frequency(mNativeWrapper.getResultMessages(), giveOsdName)); } + + @Test + public void initiateCecByWakeupMessage_selectInternalSourceAfterDelay_broadcastsActiveSource() { + HdmiCecMessage activeSourceFromTv = + HdmiCecMessageBuilder.buildActiveSource(ADDR_TV, 0x0000); + + mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_WAKE_UP_MESSAGE); + mTestLooper.dispatchAll(); + + mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS); + mTestLooper.dispatchAll(); + + mHdmiCecLocalDeviceTv.deviceSelect(ADDR_TV, new TestCallback()); + mTestLooper.dispatchAll(); + + assertThat(mNativeWrapper.getResultMessages()).contains(activeSourceFromTv); + } + + @Test + public void initiateCecByWakeupMessage_selectInternalSource_doesNotBroadcastActiveSource() { + HdmiCecMessage activeSourceFromTv = + HdmiCecMessageBuilder.buildActiveSource(ADDR_TV, 0x0000); + + mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_WAKE_UP_MESSAGE); + mTestLooper.dispatchAll(); + + mHdmiCecLocalDeviceTv.deviceSelect(ADDR_TV, new TestCallback()); + mTestLooper.dispatchAll(); + + assertThat(mNativeWrapper.getResultMessages()).doesNotContain(activeSourceFromTv); + } } diff --git a/services/tests/servicestests/src/com/android/server/pm/BackgroundInstallControlServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/BackgroundInstallControlServiceTest.java index daf18edaf2de..8656f60afc1e 100644 --- a/services/tests/servicestests/src/com/android/server/pm/BackgroundInstallControlServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/BackgroundInstallControlServiceTest.java @@ -9,13 +9,16 @@ * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.å * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.pm; +import static android.Manifest.permission.GET_BACKGROUND_INSTALLED_PACKAGES; +import static android.content.pm.PackageManager.PERMISSION_GRANTED; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; @@ -27,6 +30,7 @@ import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -97,7 +101,6 @@ public final class BackgroundInstallControlServiceTest { private Looper mLooper; private File mFile; - @Mock private Context mContext; @Mock @@ -108,8 +111,10 @@ public final class BackgroundInstallControlServiceTest { private UsageStatsManagerInternal mUsageStatsManagerInternal; @Mock private PermissionManagerServiceInternal mPermissionManager; + @Captor private ArgumentCaptor<PackageManagerInternal.PackageListObserver> mPackageListObserverCaptor; + @Captor private ArgumentCaptor<UsageEventListener> mUsageEventListenerCaptor; @@ -119,11 +124,12 @@ public final class BackgroundInstallControlServiceTest { mTestLooper = new TestLooper(); mLooper = mTestLooper.getLooper(); - mFile = new File( - InstrumentationRegistry.getInstrumentation().getContext().getCacheDir(), - "test"); - mBackgroundInstallControlService = new BackgroundInstallControlService( - new MockInjector(mContext)); + mFile = + new File( + InstrumentationRegistry.getInstrumentation().getContext().getCacheDir(), + "test"); + mBackgroundInstallControlService = + new BackgroundInstallControlService(new MockInjector(mContext)); verify(mUsageStatsManagerInternal).registerListener(mUsageEventListenerCaptor.capture()); mUsageEventListener = mUsageEventListenerCaptor.getValue(); @@ -143,8 +149,7 @@ public final class BackgroundInstallControlServiceTest { assertNull(mBackgroundInstallControlService.getBackgroundInstalledPackages()); mBackgroundInstallControlService.initBackgroundInstalledPackages(); assertNotNull(mBackgroundInstallControlService.getBackgroundInstalledPackages()); - assertEquals(0, - mBackgroundInstallControlService.getBackgroundInstalledPackages().size()); + assertEquals(0, mBackgroundInstallControlService.getBackgroundInstalledPackages().size()); } @Test @@ -161,12 +166,9 @@ public final class BackgroundInstallControlServiceTest { // Write test data to the file on the disk. try { ProtoOutputStream protoOutputStream = new ProtoOutputStream(fileOutputStream); - long token = protoOutputStream.start( - BackgroundInstalledPackagesProto.BG_INSTALLED_PKG); - protoOutputStream.write( - BackgroundInstalledPackageProto.PACKAGE_NAME, PACKAGE_NAME_1); - protoOutputStream.write( - BackgroundInstalledPackageProto.USER_ID, USER_ID_1 + 1); + long token = protoOutputStream.start(BackgroundInstalledPackagesProto.BG_INSTALLED_PKG); + protoOutputStream.write(BackgroundInstalledPackageProto.PACKAGE_NAME, PACKAGE_NAME_1); + protoOutputStream.write(BackgroundInstalledPackageProto.USER_ID, USER_ID_1 + 1); protoOutputStream.end(token); protoOutputStream.flush(); atomicFile.finishWrite(fileOutputStream); @@ -198,20 +200,14 @@ public final class BackgroundInstallControlServiceTest { try { ProtoOutputStream protoOutputStream = new ProtoOutputStream(fileOutputStream); - long token = protoOutputStream.start( - BackgroundInstalledPackagesProto.BG_INSTALLED_PKG); - protoOutputStream.write( - BackgroundInstalledPackageProto.PACKAGE_NAME, PACKAGE_NAME_1); - protoOutputStream.write( - BackgroundInstalledPackageProto.USER_ID, USER_ID_1 + 1); + long token = protoOutputStream.start(BackgroundInstalledPackagesProto.BG_INSTALLED_PKG); + protoOutputStream.write(BackgroundInstalledPackageProto.PACKAGE_NAME, PACKAGE_NAME_1); + protoOutputStream.write(BackgroundInstalledPackageProto.USER_ID, USER_ID_1 + 1); protoOutputStream.end(token); - token = protoOutputStream.start( - BackgroundInstalledPackagesProto.BG_INSTALLED_PKG); - protoOutputStream.write( - BackgroundInstalledPackageProto.PACKAGE_NAME, PACKAGE_NAME_2); - protoOutputStream.write( - BackgroundInstalledPackageProto.USER_ID, USER_ID_2 + 1); + token = protoOutputStream.start(BackgroundInstalledPackagesProto.BG_INSTALLED_PKG); + protoOutputStream.write(BackgroundInstalledPackageProto.PACKAGE_NAME, PACKAGE_NAME_2); + protoOutputStream.write(BackgroundInstalledPackageProto.USER_ID, USER_ID_2 + 1); protoOutputStream.end(token); protoOutputStream.flush(); @@ -241,7 +237,7 @@ public final class BackgroundInstallControlServiceTest { // Read the file on the disk to verify var packagesInDisk = new SparseSetArray<>(); AtomicFile atomicFile = new AtomicFile(mFile); - try (FileInputStream fileInputStream = atomicFile.openRead()) { + try (FileInputStream fileInputStream = atomicFile.openRead()) { ProtoInputStream protoInputStream = new ProtoInputStream(fileInputStream); while (protoInputStream.nextField() != ProtoInputStream.NO_MORE_FIELDS) { @@ -249,23 +245,25 @@ public final class BackgroundInstallControlServiceTest { != (int) BackgroundInstalledPackagesProto.BG_INSTALLED_PKG) { continue; } - long token = protoInputStream.start( - BackgroundInstalledPackagesProto.BG_INSTALLED_PKG); + long token = + protoInputStream.start(BackgroundInstalledPackagesProto.BG_INSTALLED_PKG); String packageName = null; int userId = UserHandle.USER_NULL; while (protoInputStream.nextField() != ProtoInputStream.NO_MORE_FIELDS) { switch (protoInputStream.getFieldNumber()) { case (int) BackgroundInstalledPackageProto.PACKAGE_NAME: - packageName = protoInputStream.readString( - BackgroundInstalledPackageProto.PACKAGE_NAME); + packageName = + protoInputStream.readString( + BackgroundInstalledPackageProto.PACKAGE_NAME); break; case (int) BackgroundInstalledPackageProto.USER_ID: - userId = protoInputStream.readInt( - BackgroundInstalledPackageProto.USER_ID) - 1; + userId = + protoInputStream.readInt( + BackgroundInstalledPackageProto.USER_ID) + - 1; break; default: - fail("Undefined field in proto: " - + protoInputStream.getFieldNumber()); + fail("Undefined field in proto: " + protoInputStream.getFieldNumber()); } } protoInputStream.end(token); @@ -296,7 +294,7 @@ public final class BackgroundInstallControlServiceTest { // Read the file on the disk to verify var packagesInDisk = new SparseSetArray<>(); AtomicFile atomicFile = new AtomicFile(mFile); - try (FileInputStream fileInputStream = atomicFile.openRead()) { + try (FileInputStream fileInputStream = atomicFile.openRead()) { ProtoInputStream protoInputStream = new ProtoInputStream(fileInputStream); while (protoInputStream.nextField() != ProtoInputStream.NO_MORE_FIELDS) { @@ -304,23 +302,25 @@ public final class BackgroundInstallControlServiceTest { != (int) BackgroundInstalledPackagesProto.BG_INSTALLED_PKG) { continue; } - long token = protoInputStream.start( - BackgroundInstalledPackagesProto.BG_INSTALLED_PKG); + long token = + protoInputStream.start(BackgroundInstalledPackagesProto.BG_INSTALLED_PKG); String packageName = null; int userId = UserHandle.USER_NULL; while (protoInputStream.nextField() != ProtoInputStream.NO_MORE_FIELDS) { switch (protoInputStream.getFieldNumber()) { case (int) BackgroundInstalledPackageProto.PACKAGE_NAME: - packageName = protoInputStream.readString( - BackgroundInstalledPackageProto.PACKAGE_NAME); + packageName = + protoInputStream.readString( + BackgroundInstalledPackageProto.PACKAGE_NAME); break; case (int) BackgroundInstalledPackageProto.USER_ID: - userId = protoInputStream.readInt( - BackgroundInstalledPackageProto.USER_ID) - 1; + userId = + protoInputStream.readInt( + BackgroundInstalledPackageProto.USER_ID) + - 1; break; default: - fail("Undefined field in proto: " - + protoInputStream.getFieldNumber()); + fail("Undefined field in proto: " + protoInputStream.getFieldNumber()); } } protoInputStream.end(token); @@ -353,7 +353,7 @@ public final class BackgroundInstallControlServiceTest { // Read the file on the disk to verify var packagesInDisk = new SparseSetArray<>(); AtomicFile atomicFile = new AtomicFile(mFile); - try (FileInputStream fileInputStream = atomicFile.openRead()) { + try (FileInputStream fileInputStream = atomicFile.openRead()) { ProtoInputStream protoInputStream = new ProtoInputStream(fileInputStream); while (protoInputStream.nextField() != ProtoInputStream.NO_MORE_FIELDS) { @@ -361,23 +361,25 @@ public final class BackgroundInstallControlServiceTest { != (int) BackgroundInstalledPackagesProto.BG_INSTALLED_PKG) { continue; } - long token = protoInputStream.start( - BackgroundInstalledPackagesProto.BG_INSTALLED_PKG); + long token = + protoInputStream.start(BackgroundInstalledPackagesProto.BG_INSTALLED_PKG); String packageName = null; int userId = UserHandle.USER_NULL; while (protoInputStream.nextField() != ProtoInputStream.NO_MORE_FIELDS) { switch (protoInputStream.getFieldNumber()) { case (int) BackgroundInstalledPackageProto.PACKAGE_NAME: - packageName = protoInputStream.readString( - BackgroundInstalledPackageProto.PACKAGE_NAME); + packageName = + protoInputStream.readString( + BackgroundInstalledPackageProto.PACKAGE_NAME); break; case (int) BackgroundInstalledPackageProto.USER_ID: - userId = protoInputStream.readInt( - BackgroundInstalledPackageProto.USER_ID) - 1; + userId = + protoInputStream.readInt( + BackgroundInstalledPackageProto.USER_ID) + - 1; break; default: - fail("Undefined field in proto: " - + protoInputStream.getFieldNumber()); + fail("Undefined field in proto: " + protoInputStream.getFieldNumber()); } } protoInputStream.end(token); @@ -399,51 +401,55 @@ public final class BackgroundInstallControlServiceTest { @Test public void testHandleUsageEvent_permissionDenied() { - assertEquals(0, - mBackgroundInstallControlService.getInstallerForegroundTimeFrames().numMaps()); - doReturn(PackageManager.PERMISSION_DENIED).when(mPermissionManager).checkPermission( - anyString(), anyString(), anyInt(), anyInt()); - generateUsageEvent(UsageEvents.Event.ACTIVITY_RESUMED, - USER_ID_1, INSTALLER_NAME_1, 0); + assertEquals( + 0, mBackgroundInstallControlService.getInstallerForegroundTimeFrames().numMaps()); + doReturn(PackageManager.PERMISSION_DENIED) + .when(mPermissionManager) + .checkPermission(anyString(), anyString(), anyInt(), anyInt()); + generateUsageEvent(UsageEvents.Event.ACTIVITY_RESUMED, USER_ID_1, INSTALLER_NAME_1, 0); mTestLooper.dispatchAll(); - assertEquals(0, - mBackgroundInstallControlService.getInstallerForegroundTimeFrames().numMaps()); + assertEquals( + 0, mBackgroundInstallControlService.getInstallerForegroundTimeFrames().numMaps()); } @Test public void testHandleUsageEvent_permissionGranted() { - assertEquals(0, - mBackgroundInstallControlService.getInstallerForegroundTimeFrames().numMaps()); - doReturn(PackageManager.PERMISSION_GRANTED).when(mPermissionManager).checkPermission( - anyString(), anyString(), anyInt(), anyInt()); - generateUsageEvent(UsageEvents.Event.ACTIVITY_RESUMED, - USER_ID_1, INSTALLER_NAME_1, 0); + assertEquals( + 0, mBackgroundInstallControlService.getInstallerForegroundTimeFrames().numMaps()); + doReturn(PERMISSION_GRANTED) + .when(mPermissionManager) + .checkPermission(anyString(), anyString(), anyInt(), anyInt()); + generateUsageEvent(UsageEvents.Event.ACTIVITY_RESUMED, USER_ID_1, INSTALLER_NAME_1, 0); mTestLooper.dispatchAll(); - assertEquals(1, - mBackgroundInstallControlService.getInstallerForegroundTimeFrames().numMaps()); + assertEquals( + 1, mBackgroundInstallControlService.getInstallerForegroundTimeFrames().numMaps()); } @Test public void testHandleUsageEvent_ignoredEvent() { - assertEquals(0, - mBackgroundInstallControlService.getInstallerForegroundTimeFrames().numMaps()); - doReturn(PackageManager.PERMISSION_GRANTED).when(mPermissionManager).checkPermission( - anyString(), anyString(), anyInt(), anyInt()); - generateUsageEvent(UsageEvents.Event.USER_INTERACTION, - USER_ID_1, INSTALLER_NAME_1, 0); + assertEquals( + 0, mBackgroundInstallControlService.getInstallerForegroundTimeFrames().numMaps()); + doReturn(PERMISSION_GRANTED) + .when(mPermissionManager) + .checkPermission(anyString(), anyString(), anyInt(), anyInt()); + generateUsageEvent(UsageEvents.Event.USER_INTERACTION, USER_ID_1, INSTALLER_NAME_1, 0); mTestLooper.dispatchAll(); - assertEquals(0, - mBackgroundInstallControlService.getInstallerForegroundTimeFrames().numMaps()); + assertEquals( + 0, mBackgroundInstallControlService.getInstallerForegroundTimeFrames().numMaps()); } @Test public void testHandleUsageEvent_firstActivityResumedHalfTimeFrame() { - assertEquals(0, - mBackgroundInstallControlService.getInstallerForegroundTimeFrames().numMaps()); - doReturn(PackageManager.PERMISSION_GRANTED).when(mPermissionManager).checkPermission( - anyString(), anyString(), anyInt(), anyInt()); - generateUsageEvent(UsageEvents.Event.ACTIVITY_RESUMED, - USER_ID_1, INSTALLER_NAME_1, USAGE_EVENT_TIMESTAMP_1); + assertEquals( + 0, mBackgroundInstallControlService.getInstallerForegroundTimeFrames().numMaps()); + doReturn(PERMISSION_GRANTED) + .when(mPermissionManager) + .checkPermission(anyString(), anyString(), anyInt(), anyInt()); + generateUsageEvent( + UsageEvents.Event.ACTIVITY_RESUMED, + USER_ID_1, + INSTALLER_NAME_1, + USAGE_EVENT_TIMESTAMP_1); mTestLooper.dispatchAll(); var installerForegroundTimeFrames = @@ -461,14 +467,18 @@ public final class BackgroundInstallControlServiceTest { @Test public void testHandleUsageEvent_firstActivityResumedOneTimeFrame() { - assertEquals(0, - mBackgroundInstallControlService.getInstallerForegroundTimeFrames().numMaps()); - doReturn(PackageManager.PERMISSION_GRANTED).when(mPermissionManager).checkPermission( - anyString(), anyString(), anyInt(), anyInt()); - generateUsageEvent(UsageEvents.Event.ACTIVITY_RESUMED, - USER_ID_1, INSTALLER_NAME_1, USAGE_EVENT_TIMESTAMP_1); - generateUsageEvent(Event.ACTIVITY_STOPPED, - USER_ID_1, INSTALLER_NAME_1, USAGE_EVENT_TIMESTAMP_2); + assertEquals( + 0, mBackgroundInstallControlService.getInstallerForegroundTimeFrames().numMaps()); + doReturn(PERMISSION_GRANTED) + .when(mPermissionManager) + .checkPermission(anyString(), anyString(), anyInt(), anyInt()); + generateUsageEvent( + UsageEvents.Event.ACTIVITY_RESUMED, + USER_ID_1, + INSTALLER_NAME_1, + USAGE_EVENT_TIMESTAMP_1); + generateUsageEvent( + Event.ACTIVITY_STOPPED, USER_ID_1, INSTALLER_NAME_1, USAGE_EVENT_TIMESTAMP_2); mTestLooper.dispatchAll(); var installerForegroundTimeFrames = @@ -486,16 +496,23 @@ public final class BackgroundInstallControlServiceTest { @Test public void testHandleUsageEvent_firstActivityResumedOneAndHalfTimeFrame() { - assertEquals(0, - mBackgroundInstallControlService.getInstallerForegroundTimeFrames().numMaps()); - doReturn(PackageManager.PERMISSION_GRANTED).when(mPermissionManager).checkPermission( - anyString(), anyString(), anyInt(), anyInt()); - generateUsageEvent(UsageEvents.Event.ACTIVITY_RESUMED, - USER_ID_1, INSTALLER_NAME_1, USAGE_EVENT_TIMESTAMP_1); - generateUsageEvent(Event.ACTIVITY_STOPPED, - USER_ID_1, INSTALLER_NAME_1, USAGE_EVENT_TIMESTAMP_2); - generateUsageEvent(UsageEvents.Event.ACTIVITY_RESUMED, - USER_ID_1, INSTALLER_NAME_1, USAGE_EVENT_TIMESTAMP_3); + assertEquals( + 0, mBackgroundInstallControlService.getInstallerForegroundTimeFrames().numMaps()); + doReturn(PERMISSION_GRANTED) + .when(mPermissionManager) + .checkPermission(anyString(), anyString(), anyInt(), anyInt()); + generateUsageEvent( + UsageEvents.Event.ACTIVITY_RESUMED, + USER_ID_1, + INSTALLER_NAME_1, + USAGE_EVENT_TIMESTAMP_1); + generateUsageEvent( + Event.ACTIVITY_STOPPED, USER_ID_1, INSTALLER_NAME_1, USAGE_EVENT_TIMESTAMP_2); + generateUsageEvent( + UsageEvents.Event.ACTIVITY_RESUMED, + USER_ID_1, + INSTALLER_NAME_1, + USAGE_EVENT_TIMESTAMP_3); mTestLooper.dispatchAll(); var installerForegroundTimeFrames = @@ -517,12 +534,13 @@ public final class BackgroundInstallControlServiceTest { @Test public void testHandleUsageEvent_firstNoneActivityResumed() { - assertEquals(0, - mBackgroundInstallControlService.getInstallerForegroundTimeFrames().numMaps()); - doReturn(PackageManager.PERMISSION_GRANTED).when(mPermissionManager).checkPermission( - anyString(), anyString(), anyInt(), anyInt()); - generateUsageEvent(Event.ACTIVITY_STOPPED, - USER_ID_1, INSTALLER_NAME_1, USAGE_EVENT_TIMESTAMP_1); + assertEquals( + 0, mBackgroundInstallControlService.getInstallerForegroundTimeFrames().numMaps()); + doReturn(PERMISSION_GRANTED) + .when(mPermissionManager) + .checkPermission(anyString(), anyString(), anyInt(), anyInt()); + generateUsageEvent( + Event.ACTIVITY_STOPPED, USER_ID_1, INSTALLER_NAME_1, USAGE_EVENT_TIMESTAMP_1); mTestLooper.dispatchAll(); var installerForegroundTimeFrames = @@ -535,27 +553,26 @@ public final class BackgroundInstallControlServiceTest { } @Test - public void testHandleUsageEvent_packageAddedNoUsageEvent() throws - NoSuchFieldException, PackageManager.NameNotFoundException { + public void testHandleUsageEvent_packageAddedNoUsageEvent() + throws NoSuchFieldException, PackageManager.NameNotFoundException { assertNull(mBackgroundInstallControlService.getBackgroundInstalledPackages()); - InstallSourceInfo installSourceInfo = new InstallSourceInfo( - /* initiatingPackageName = */ INSTALLER_NAME_1, - /* initiatingPackageSigningInfo = */ null, - /* originatingPackageName = */ null, - /* installingPackageName = */ INSTALLER_NAME_1); + InstallSourceInfo installSourceInfo = + new InstallSourceInfo( + /* initiatingPackageName= */ INSTALLER_NAME_1, + /* initiatingPackageSigningInfo= */ null, + /* originatingPackageName= */ null, + /* installingPackageName= */ INSTALLER_NAME_1); assertEquals(installSourceInfo.getInstallingPackageName(), INSTALLER_NAME_1); when(mPackageManager.getInstallSourceInfo(anyString())).thenReturn(installSourceInfo); ApplicationInfo appInfo = mock(ApplicationInfo.class); - when(mPackageManager.getApplicationInfoAsUser( - eq(PACKAGE_NAME_1), - any(), - anyInt()) - ).thenReturn(appInfo); + when(mPackageManager.getApplicationInfoAsUser(eq(PACKAGE_NAME_1), any(), anyInt())) + .thenReturn(appInfo); - long createTimestamp = PACKAGE_ADD_TIMESTAMP_1 - - (System.currentTimeMillis() - SystemClock.uptimeMillis()); - FieldSetter.setField(appInfo, + long createTimestamp = + PACKAGE_ADD_TIMESTAMP_1 - (System.currentTimeMillis() - SystemClock.uptimeMillis()); + FieldSetter.setField( + appInfo, ApplicationInfo.class.getDeclaredField("createTimestamp"), createTimestamp); @@ -572,27 +589,26 @@ public final class BackgroundInstallControlServiceTest { } @Test - public void testHandleUsageEvent_packageAddedInsideTimeFrame() throws - NoSuchFieldException, PackageManager.NameNotFoundException { + public void testHandleUsageEvent_packageAddedInsideTimeFrame() + throws NoSuchFieldException, PackageManager.NameNotFoundException { assertNull(mBackgroundInstallControlService.getBackgroundInstalledPackages()); - InstallSourceInfo installSourceInfo = new InstallSourceInfo( - /* initiatingPackageName = */ INSTALLER_NAME_1, - /* initiatingPackageSigningInfo = */ null, - /* originatingPackageName = */ null, - /* installingPackageName = */ INSTALLER_NAME_1); + InstallSourceInfo installSourceInfo = + new InstallSourceInfo( + /* initiatingPackageName= */ INSTALLER_NAME_1, + /* initiatingPackageSigningInfo= */ null, + /* originatingPackageName= */ null, + /* installingPackageName= */ INSTALLER_NAME_1); assertEquals(installSourceInfo.getInstallingPackageName(), INSTALLER_NAME_1); when(mPackageManager.getInstallSourceInfo(anyString())).thenReturn(installSourceInfo); ApplicationInfo appInfo = mock(ApplicationInfo.class); - when(mPackageManager.getApplicationInfoAsUser( - eq(PACKAGE_NAME_1), - any(), - anyInt()) - ).thenReturn(appInfo); + when(mPackageManager.getApplicationInfoAsUser(eq(PACKAGE_NAME_1), any(), anyInt())) + .thenReturn(appInfo); - long createTimestamp = PACKAGE_ADD_TIMESTAMP_1 - - (System.currentTimeMillis() - SystemClock.uptimeMillis()); - FieldSetter.setField(appInfo, + long createTimestamp = + PACKAGE_ADD_TIMESTAMP_1 - (System.currentTimeMillis() - SystemClock.uptimeMillis()); + FieldSetter.setField( + appInfo, ApplicationInfo.class.getDeclaredField("createTimestamp"), createTimestamp); @@ -604,12 +620,16 @@ public final class BackgroundInstallControlServiceTest { // The 2 usage events make the package adding inside a time frame. // So it's not a background install. Thus, it's null for the return of // mBackgroundInstallControlService.getBackgroundInstalledPackages() - doReturn(PackageManager.PERMISSION_GRANTED).when(mPermissionManager).checkPermission( - anyString(), anyString(), anyInt(), anyInt()); - generateUsageEvent(UsageEvents.Event.ACTIVITY_RESUMED, - USER_ID_1, INSTALLER_NAME_1, USAGE_EVENT_TIMESTAMP_1); - generateUsageEvent(Event.ACTIVITY_STOPPED, - USER_ID_1, INSTALLER_NAME_1, USAGE_EVENT_TIMESTAMP_2); + doReturn(PERMISSION_GRANTED) + .when(mPermissionManager) + .checkPermission(anyString(), anyString(), anyInt(), anyInt()); + generateUsageEvent( + UsageEvents.Event.ACTIVITY_RESUMED, + USER_ID_1, + INSTALLER_NAME_1, + USAGE_EVENT_TIMESTAMP_1); + generateUsageEvent( + Event.ACTIVITY_STOPPED, USER_ID_1, INSTALLER_NAME_1, USAGE_EVENT_TIMESTAMP_2); mPackageListObserver.onPackageAdded(PACKAGE_NAME_1, uid); mTestLooper.dispatchAll(); @@ -617,27 +637,26 @@ public final class BackgroundInstallControlServiceTest { } @Test - public void testHandleUsageEvent_packageAddedOutsideTimeFrame1() throws - NoSuchFieldException, PackageManager.NameNotFoundException { + public void testHandleUsageEvent_packageAddedOutsideTimeFrame1() + throws NoSuchFieldException, PackageManager.NameNotFoundException { assertNull(mBackgroundInstallControlService.getBackgroundInstalledPackages()); - InstallSourceInfo installSourceInfo = new InstallSourceInfo( - /* initiatingPackageName = */ INSTALLER_NAME_1, - /* initiatingPackageSigningInfo = */ null, - /* originatingPackageName = */ null, - /* installingPackageName = */ INSTALLER_NAME_1); + InstallSourceInfo installSourceInfo = + new InstallSourceInfo( + /* initiatingPackageName= */ INSTALLER_NAME_1, + /* initiatingPackageSigningInfo= */ null, + /* originatingPackageName= */ null, + /* installingPackageName= */ INSTALLER_NAME_1); assertEquals(installSourceInfo.getInstallingPackageName(), INSTALLER_NAME_1); when(mPackageManager.getInstallSourceInfo(anyString())).thenReturn(installSourceInfo); ApplicationInfo appInfo = mock(ApplicationInfo.class); - when(mPackageManager.getApplicationInfoAsUser( - eq(PACKAGE_NAME_1), - any(), - anyInt()) - ).thenReturn(appInfo); + when(mPackageManager.getApplicationInfoAsUser(eq(PACKAGE_NAME_1), any(), anyInt())) + .thenReturn(appInfo); - long createTimestamp = PACKAGE_ADD_TIMESTAMP_1 - - (System.currentTimeMillis() - SystemClock.uptimeMillis()); - FieldSetter.setField(appInfo, + long createTimestamp = + PACKAGE_ADD_TIMESTAMP_1 - (System.currentTimeMillis() - SystemClock.uptimeMillis()); + FieldSetter.setField( + appInfo, ApplicationInfo.class.getDeclaredField("createTimestamp"), createTimestamp); @@ -650,12 +669,16 @@ public final class BackgroundInstallControlServiceTest { // Compared to testHandleUsageEvent_packageAddedInsideTimeFrame, // it's a background install. Thus, it's not null for the return of // mBackgroundInstallControlService.getBackgroundInstalledPackages() - doReturn(PackageManager.PERMISSION_GRANTED).when(mPermissionManager).checkPermission( - anyString(), anyString(), anyInt(), anyInt()); - generateUsageEvent(UsageEvents.Event.ACTIVITY_RESUMED, - USER_ID_1, INSTALLER_NAME_1, USAGE_EVENT_TIMESTAMP_2); - generateUsageEvent(Event.ACTIVITY_STOPPED, - USER_ID_1, INSTALLER_NAME_1, USAGE_EVENT_TIMESTAMP_3); + doReturn(PERMISSION_GRANTED) + .when(mPermissionManager) + .checkPermission(anyString(), anyString(), anyInt(), anyInt()); + generateUsageEvent( + UsageEvents.Event.ACTIVITY_RESUMED, + USER_ID_1, + INSTALLER_NAME_1, + USAGE_EVENT_TIMESTAMP_2); + generateUsageEvent( + Event.ACTIVITY_STOPPED, USER_ID_1, INSTALLER_NAME_1, USAGE_EVENT_TIMESTAMP_3); mPackageListObserver.onPackageAdded(PACKAGE_NAME_1, uid); mTestLooper.dispatchAll(); @@ -665,28 +688,28 @@ public final class BackgroundInstallControlServiceTest { assertEquals(1, packages.size()); assertTrue(packages.contains(USER_ID_1, PACKAGE_NAME_1)); } + @Test - public void testHandleUsageEvent_packageAddedOutsideTimeFrame2() throws - NoSuchFieldException, PackageManager.NameNotFoundException { + public void testHandleUsageEvent_packageAddedOutsideTimeFrame2() + throws NoSuchFieldException, PackageManager.NameNotFoundException { assertNull(mBackgroundInstallControlService.getBackgroundInstalledPackages()); - InstallSourceInfo installSourceInfo = new InstallSourceInfo( - /* initiatingPackageName = */ INSTALLER_NAME_1, - /* initiatingPackageSigningInfo = */ null, - /* originatingPackageName = */ null, - /* installingPackageName = */ INSTALLER_NAME_1); + InstallSourceInfo installSourceInfo = + new InstallSourceInfo( + /* initiatingPackageName= */ INSTALLER_NAME_1, + /* initiatingPackageSigningInfo= */ null, + /* originatingPackageName= */ null, + /* installingPackageName= */ INSTALLER_NAME_1); assertEquals(installSourceInfo.getInstallingPackageName(), INSTALLER_NAME_1); when(mPackageManager.getInstallSourceInfo(anyString())).thenReturn(installSourceInfo); ApplicationInfo appInfo = mock(ApplicationInfo.class); - when(mPackageManager.getApplicationInfoAsUser( - eq(PACKAGE_NAME_1), - any(), - anyInt()) - ).thenReturn(appInfo); + when(mPackageManager.getApplicationInfoAsUser(eq(PACKAGE_NAME_1), any(), anyInt())) + .thenReturn(appInfo); - long createTimestamp = PACKAGE_ADD_TIMESTAMP_1 - - (System.currentTimeMillis() - SystemClock.uptimeMillis()); - FieldSetter.setField(appInfo, + long createTimestamp = + PACKAGE_ADD_TIMESTAMP_1 - (System.currentTimeMillis() - SystemClock.uptimeMillis()); + FieldSetter.setField( + appInfo, ApplicationInfo.class.getDeclaredField("createTimestamp"), createTimestamp); @@ -700,12 +723,16 @@ public final class BackgroundInstallControlServiceTest { // Compared to testHandleUsageEvent_packageAddedInsideTimeFrame, // it's a background install. Thus, it's not null for the return of // mBackgroundInstallControlService.getBackgroundInstalledPackages() - doReturn(PackageManager.PERMISSION_GRANTED).when(mPermissionManager).checkPermission( - anyString(), anyString(), anyInt(), anyInt()); - generateUsageEvent(UsageEvents.Event.ACTIVITY_RESUMED, - USER_ID_2, INSTALLER_NAME_2, USAGE_EVENT_TIMESTAMP_2); - generateUsageEvent(Event.ACTIVITY_STOPPED, - USER_ID_2, INSTALLER_NAME_2, USAGE_EVENT_TIMESTAMP_3); + doReturn(PERMISSION_GRANTED) + .when(mPermissionManager) + .checkPermission(anyString(), anyString(), anyInt(), anyInt()); + generateUsageEvent( + UsageEvents.Event.ACTIVITY_RESUMED, + USER_ID_2, + INSTALLER_NAME_2, + USAGE_EVENT_TIMESTAMP_2); + generateUsageEvent( + Event.ACTIVITY_STOPPED, USER_ID_2, INSTALLER_NAME_2, USAGE_EVENT_TIMESTAMP_3); mPackageListObserver.onPackageAdded(PACKAGE_NAME_1, uid); mTestLooper.dispatchAll(); @@ -715,31 +742,31 @@ public final class BackgroundInstallControlServiceTest { assertEquals(1, packages.size()); assertTrue(packages.contains(USER_ID_1, PACKAGE_NAME_1)); } + @Test - public void testHandleUsageEvent_packageAddedThroughAdb() throws - NoSuchFieldException, PackageManager.NameNotFoundException { + public void testHandleUsageEvent_packageAddedThroughAdb() + throws NoSuchFieldException, PackageManager.NameNotFoundException { assertNull(mBackgroundInstallControlService.getBackgroundInstalledPackages()); // This test is a duplicate of testHandleUsageEvent_packageAddedThroughAdb except the // initiatingPackageName used to be null but is now "com.android.shell". This test ensures // that the behavior is still the same for when the initiatingPackageName is null. - InstallSourceInfo installSourceInfo = new InstallSourceInfo( - /* initiatingPackageName = */ null, - /* initiatingPackageSigningInfo = */ null, - /* originatingPackageName = */ null, - /* installingPackageName = */ INSTALLER_NAME_1); + InstallSourceInfo installSourceInfo = + new InstallSourceInfo( + /* initiatingPackageName= */ null, + /* initiatingPackageSigningInfo= */ null, + /* originatingPackageName= */ null, + /* installingPackageName= */ INSTALLER_NAME_1); // b/265203007 when(mPackageManager.getInstallSourceInfo(anyString())).thenReturn(installSourceInfo); ApplicationInfo appInfo = mock(ApplicationInfo.class); - when(mPackageManager.getApplicationInfoAsUser( - eq(PACKAGE_NAME_1), - any(), - anyInt()) - ).thenReturn(appInfo); + when(mPackageManager.getApplicationInfoAsUser(eq(PACKAGE_NAME_1), any(), anyInt())) + .thenReturn(appInfo); - long createTimestamp = PACKAGE_ADD_TIMESTAMP_1 - - (System.currentTimeMillis() - SystemClock.uptimeMillis()); - FieldSetter.setField(appInfo, + long createTimestamp = + PACKAGE_ADD_TIMESTAMP_1 - (System.currentTimeMillis() - SystemClock.uptimeMillis()); + FieldSetter.setField( + appInfo, ApplicationInfo.class.getDeclaredField("createTimestamp"), createTimestamp); @@ -751,12 +778,16 @@ public final class BackgroundInstallControlServiceTest { // for ADB installs the initiatingPackageName used to be null, despite being detected // as a background install. Since we do not want to treat side-loaded apps as background // install getBackgroundInstalledPackages() is expected to return null - doReturn(PackageManager.PERMISSION_GRANTED).when(mPermissionManager).checkPermission( - anyString(), anyString(), anyInt(), anyInt()); - generateUsageEvent(UsageEvents.Event.ACTIVITY_RESUMED, - USER_ID_1, INSTALLER_NAME_1, USAGE_EVENT_TIMESTAMP_2); - generateUsageEvent(Event.ACTIVITY_STOPPED, - USER_ID_1, INSTALLER_NAME_1, USAGE_EVENT_TIMESTAMP_3); + doReturn(PERMISSION_GRANTED) + .when(mPermissionManager) + .checkPermission(anyString(), anyString(), anyInt(), anyInt()); + generateUsageEvent( + UsageEvents.Event.ACTIVITY_RESUMED, + USER_ID_1, + INSTALLER_NAME_1, + USAGE_EVENT_TIMESTAMP_2); + generateUsageEvent( + Event.ACTIVITY_STOPPED, USER_ID_1, INSTALLER_NAME_1, USAGE_EVENT_TIMESTAMP_3); mPackageListObserver.onPackageAdded(PACKAGE_NAME_1, uid); mTestLooper.dispatchAll(); @@ -764,31 +795,31 @@ public final class BackgroundInstallControlServiceTest { var packages = mBackgroundInstallControlService.getBackgroundInstalledPackages(); assertNull(packages); } + @Test - public void testHandleUsageEvent_packageAddedThroughAdb2() throws - NoSuchFieldException, PackageManager.NameNotFoundException { + public void testHandleUsageEvent_packageAddedThroughAdb2() + throws NoSuchFieldException, PackageManager.NameNotFoundException { assertNull(mBackgroundInstallControlService.getBackgroundInstalledPackages()); // This test is a duplicate of testHandleUsageEvent_packageAddedThroughAdb except the // initiatingPackageName used to be null but is now "com.android.shell". This test ensures // that the behavior is still the same after this change. - InstallSourceInfo installSourceInfo = new InstallSourceInfo( - /* initiatingPackageName = */ "com.android.shell", - /* initiatingPackageSigningInfo = */ null, - /* originatingPackageName = */ null, - /* installingPackageName = */ INSTALLER_NAME_1); + InstallSourceInfo installSourceInfo = + new InstallSourceInfo( + /* initiatingPackageName= */ "com.android.shell", + /* initiatingPackageSigningInfo= */ null, + /* originatingPackageName= */ null, + /* installingPackageName= */ INSTALLER_NAME_1); // b/265203007 when(mPackageManager.getInstallSourceInfo(anyString())).thenReturn(installSourceInfo); ApplicationInfo appInfo = mock(ApplicationInfo.class); - when(mPackageManager.getApplicationInfoAsUser( - eq(PACKAGE_NAME_1), - any(), - anyInt()) - ).thenReturn(appInfo); + when(mPackageManager.getApplicationInfoAsUser(eq(PACKAGE_NAME_1), any(), anyInt())) + .thenReturn(appInfo); - long createTimestamp = PACKAGE_ADD_TIMESTAMP_1 - - (System.currentTimeMillis() - SystemClock.uptimeMillis()); - FieldSetter.setField(appInfo, + long createTimestamp = + PACKAGE_ADD_TIMESTAMP_1 - (System.currentTimeMillis() - SystemClock.uptimeMillis()); + FieldSetter.setField( + appInfo, ApplicationInfo.class.getDeclaredField("createTimestamp"), createTimestamp); @@ -800,12 +831,16 @@ public final class BackgroundInstallControlServiceTest { // for ADB installs the initiatingPackageName is com.android.shell, despite being detected // as a background install. Since we do not want to treat side-loaded apps as background // install getBackgroundInstalledPackages() is expected to return null - doReturn(PackageManager.PERMISSION_GRANTED).when(mPermissionManager).checkPermission( - anyString(), anyString(), anyInt(), anyInt()); - generateUsageEvent(UsageEvents.Event.ACTIVITY_RESUMED, - USER_ID_1, INSTALLER_NAME_1, USAGE_EVENT_TIMESTAMP_2); - generateUsageEvent(Event.ACTIVITY_STOPPED, - USER_ID_1, INSTALLER_NAME_1, USAGE_EVENT_TIMESTAMP_3); + doReturn(PERMISSION_GRANTED) + .when(mPermissionManager) + .checkPermission(anyString(), anyString(), anyInt(), anyInt()); + generateUsageEvent( + UsageEvents.Event.ACTIVITY_RESUMED, + USER_ID_1, + INSTALLER_NAME_1, + USAGE_EVENT_TIMESTAMP_2); + generateUsageEvent( + Event.ACTIVITY_STOPPED, USER_ID_1, INSTALLER_NAME_1, USAGE_EVENT_TIMESTAMP_3); mPackageListObserver.onPackageAdded(PACKAGE_NAME_1, uid); mTestLooper.dispatchAll(); @@ -813,6 +848,7 @@ public final class BackgroundInstallControlServiceTest { var packages = mBackgroundInstallControlService.getBackgroundInstalledPackages(); assertNull(packages); } + @Test public void testPackageRemoved() { assertNull(mBackgroundInstallControlService.getBackgroundInstalledPackages()); @@ -859,8 +895,7 @@ public final class BackgroundInstallControlServiceTest { packages.add(packageInfo2); var packageInfo3 = makePackageInfo(PACKAGE_NAME_3); packages.add(packageInfo3); - doReturn(packages).when(mPackageManager).getInstalledPackagesAsUser( - any(), anyInt()); + doReturn(packages).when(mPackageManager).getInstalledPackagesAsUser(any(), anyInt()); var resultPackages = mBackgroundInstallControlService.getBackgroundInstalledPackages(0L, USER_ID_1); @@ -870,18 +905,30 @@ public final class BackgroundInstallControlServiceTest { assertFalse(resultPackages.getList().contains(packageInfo3)); } + @Test(expected = SecurityException.class) + public void enforceCallerPermissionsThrowsSecurityException() { + doThrow(new SecurityException("test")).when(mContext) + .enforceCallingOrSelfPermission(eq(GET_BACKGROUND_INSTALLED_PACKAGES), anyString()); + + mBackgroundInstallControlService.enforceCallerPermissions(); + } + + @Test + public void enforceCallerPermissionsDoesNotThrowSecurityException() { + //enforceCallerQueryPackagesPermissions do not throw + + mBackgroundInstallControlService.enforceCallerPermissions(); + } + /** * Mock a usage event occurring. * * @param usageEventId id of a usage event - * @param userId user id of a usage event - * @param pkgName package name of a usage event - * @param timestamp timestamp of a usage event + * @param userId user id of a usage event + * @param pkgName package name of a usage event + * @param timestamp timestamp of a usage event */ - private void generateUsageEvent(int usageEventId, - int userId, - String pkgName, - long timestamp) { + private void generateUsageEvent(int usageEventId, int userId, String pkgName, long timestamp) { Event event = new Event(usageEventId, timestamp); event.mPackage = pkgName; mUsageEventListener.onUsageEvent(userId, event); diff --git a/services/tests/servicestests/src/com/android/server/rollback/RollbackStoreTest.java b/services/tests/servicestests/src/com/android/server/rollback/RollbackStoreTest.java index 9d56a36196bb..5e11e17f9414 100644 --- a/services/tests/servicestests/src/com/android/server/rollback/RollbackStoreTest.java +++ b/services/tests/servicestests/src/com/android/server/rollback/RollbackStoreTest.java @@ -18,6 +18,7 @@ package com.android.server.rollback; import static com.google.common.truth.Truth.assertThat; +import android.content.pm.PackageManager; import android.content.pm.VersionedPackage; import android.content.rollback.PackageRollbackInfo; import android.util.SparseIntArray; @@ -81,7 +82,8 @@ public class RollbackStoreTest { + "'installedUsers':[55,79]," + "'ceSnapshotInodes':[]}],'isStaged':false,'causePackages':[{'packageName':'hello'," + "'longVersionCode':23},{'packageName':'something','longVersionCode':999}]," - + "'committedSessionId':45654465},'timestamp':'2019-10-01T12:29:08.855Z'," + + "'committedSessionId':45654465, 'rollbackImpactLevel':1}," + + "'timestamp':'2019-10-01T12:29:08.855Z'," + "'originalSessionId':567,'state':'enabling','apkSessionId':-1," + "'restoreUserDataInProgress':true, 'userId':0," + "'installerPackageName':'some.installer'}"; @@ -138,6 +140,8 @@ public class RollbackStoreTest { assertThat(rollback.getOriginalSessionId()).isEqualTo(567); assertThat(rollback.info.getRollbackId()).isEqualTo(ID); assertThat(rollback.info.getPackages()).isEmpty(); + assertThat(rollback.info.getRollbackImpactLevel()).isEqualTo( + PackageManager.ROLLBACK_USER_IMPACT_LOW); assertThat(rollback.isEnabling()).isTrue(); assertThat(rollback.getExtensionVersions().toString()) .isEqualTo(extensionVersions.toString()); @@ -158,6 +162,8 @@ public class RollbackStoreTest { assertThat(rollback.info.getRollbackId()).isEqualTo(ID); assertThat(rollback.info.getPackages()).isEmpty(); + assertThat(rollback.info.getRollbackImpactLevel()).isEqualTo( + PackageManager.ROLLBACK_USER_IMPACT_LOW); assertThat(rollback.isEnabling()).isTrue(); assertThat(rollback.getExtensionVersions().toString()) .isEqualTo(extensionVersions.toString()); @@ -175,6 +181,7 @@ public class RollbackStoreTest { origRb.info.getCausePackages().add(new VersionedPackage("com.made.up", 2)); origRb.info.getCausePackages().add(new VersionedPackage("com.pack.age", 99)); origRb.info.setCommittedSessionId(123456); + origRb.info.setRollbackImpactLevel(PackageManager.ROLLBACK_USER_IMPACT_HIGH); PackageRollbackInfo pkgInfo1 = new PackageRollbackInfo(new VersionedPackage("com.made.up", 18), @@ -226,6 +233,7 @@ public class RollbackStoreTest { expectedRb.info.getCausePackages().add(new VersionedPackage("hello", 23)); expectedRb.info.getCausePackages().add(new VersionedPackage("something", 999)); expectedRb.info.setCommittedSessionId(45654465); + expectedRb.info.setRollbackImpactLevel(PackageManager.ROLLBACK_USER_IMPACT_HIGH); PackageRollbackInfo pkgInfo1 = new PackageRollbackInfo(new VersionedPackage("blah", 55), new VersionedPackage("blah1", 50), new ArrayList<>(), new ArrayList<>(), diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationVisitUrisTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationVisitUrisTest.java index ea948ca0e28b..863cda4905f1 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationVisitUrisTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationVisitUrisTest.java @@ -118,12 +118,19 @@ public class NotificationVisitUrisTest extends UiServiceTestCase { // Constructors that should be used to create instances of specific classes. Overrides scoring. private static final ImmutableMap<Class<?>, Constructor<?>> PREFERRED_CONSTRUCTORS; + // Setter methods that receive String parameters, but where those Strings represent Uris + // (and are visited/validated). + private static final ImmutableSet<Method> SETTERS_WITH_STRING_AS_URI; + static { try { PREFERRED_CONSTRUCTORS = ImmutableMap.of( Notification.Builder.class, Notification.Builder.class.getConstructor(Context.class, String.class)); + SETTERS_WITH_STRING_AS_URI = ImmutableSet.of( + Person.Builder.class.getMethod("setUri", String.class)); + EXCLUDED_SETTERS_OVERLOADS = ImmutableMultimap.<Class<?>, Method>builder() .put(RemoteViews.class, // b/245950570: Tries to connect to service and will crash. @@ -257,7 +264,7 @@ public class NotificationVisitUrisTest extends UiServiceTestCase { @Nullable Class<?> styleClass, @Nullable Class<?> extenderClass, @Nullable Class<?> actionExtenderClass, boolean includeRemoteViews) { SpecialParameterGenerator specialGenerator = new SpecialParameterGenerator(context); - Set<Class<?>> excludedClasses = includeRemoteViews + ImmutableSet<Class<?>> excludedClasses = includeRemoteViews ? ImmutableSet.of() : ImmutableSet.of(RemoteViews.class); Location location = Location.root(Notification.Builder.class); @@ -294,7 +301,7 @@ public class NotificationVisitUrisTest extends UiServiceTestCase { } private static Object generateObject(Class<?> clazz, Location where, - Set<Class<?>> excludingClasses, SpecialParameterGenerator specialGenerator) { + ImmutableSet<Class<?>> excludingClasses, SpecialParameterGenerator specialGenerator) { if (excludingClasses.contains(clazz)) { throw new IllegalArgumentException( String.format("Asked to generate a %s but it's part of the excluded set (%s)", @@ -369,7 +376,7 @@ public class NotificationVisitUrisTest extends UiServiceTestCase { } private static Object constructEmpty(Class<?> clazz, Location where, - Set<Class<?>> excludingClasses, SpecialParameterGenerator specialGenerator) { + ImmutableSet<Class<?>> excludingClasses, SpecialParameterGenerator specialGenerator) { Constructor<?> bestConstructor; if (PREFERRED_CONSTRUCTORS.containsKey(clazz)) { // Use the preferred constructor. @@ -431,7 +438,7 @@ public class NotificationVisitUrisTest extends UiServiceTestCase { } private static void invokeAllSetters(Object instance, Location where, boolean allOverloads, - boolean includingVoidMethods, Set<Class<?>> excludingParameterTypes, + boolean includingVoidMethods, ImmutableSet<Class<?>> excludingParameterTypes, SpecialParameterGenerator specialGenerator) { for (Method setter : ReflectionUtils.getAllSetters(instance.getClass(), where, allOverloads, includingVoidMethods, excludingParameterTypes)) { @@ -462,24 +469,34 @@ public class NotificationVisitUrisTest extends UiServiceTestCase { } private static Object[] generateParameters(Executable executable, Location where, - Set<Class<?>> excludingClasses, SpecialParameterGenerator specialGenerator) { + ImmutableSet<Class<?>> excludingClasses, SpecialParameterGenerator specialGenerator) { Log.i(TAG, "About to generate parameters for " + ReflectionUtils.methodToString(executable) + " in " + where); Type[] parameterTypes = executable.getGenericParameterTypes(); Object[] parameterValues = new Object[parameterTypes.length]; for (int i = 0; i < parameterTypes.length; i++) { - parameterValues[i] = generateParameter( - parameterTypes[i], + boolean generateUriAsString = false; + Type parameterType = parameterTypes[i]; + if (SETTERS_WITH_STRING_AS_URI.contains(executable) + && parameterType.equals(String.class)) { + generateUriAsString = true; + } + Object value = generateParameter( + generateUriAsString ? Uri.class : parameterType, where.plus(executable, String.format("[%d,%s]", i, parameterTypes[i].getTypeName())), excludingClasses, specialGenerator); + if (generateUriAsString) { + value = ((Uri) value).toString(); + } + parameterValues[i] = value; } return parameterValues; } private static Object generateParameter(Type parameterType, Location where, - Set<Class<?>> excludingClasses, SpecialParameterGenerator specialGenerator) { + ImmutableSet<Class<?>> excludingClasses, SpecialParameterGenerator specialGenerator) { if (parameterType instanceof Class<?> parameterClass) { return generateObject( parameterClass, @@ -487,7 +504,8 @@ public class NotificationVisitUrisTest extends UiServiceTestCase { excludingClasses, specialGenerator); } else if (parameterType instanceof ParameterizedType parameterizedType) { - if (parameterizedType.getRawType().equals(List.class) + if ((parameterizedType.getRawType().equals(List.class) + || parameterizedType.getRawType().equals(ArrayList.class)) && parameterizedType.getActualTypeArguments()[0] instanceof Class<?>) { ArrayList listValue = new ArrayList(); for (int i = 0; i < NUM_ELEMENTS_IN_ARRAY; i++) { @@ -503,12 +521,14 @@ public class NotificationVisitUrisTest extends UiServiceTestCase { } private static class ReflectionUtils { - static Set<Class<?>> getConcreteSubclasses(Class<?> clazz, Class<?> containerClass) { - return Arrays.stream(containerClass.getDeclaredClasses()) - .filter( - innerClass -> clazz.isAssignableFrom(innerClass) - && !Modifier.isAbstract(innerClass.getModifiers())) - .collect(Collectors.toSet()); + static ImmutableSet<Class<?>> getConcreteSubclasses(Class<?> clazz, + Class<?> containerClass) { + return ImmutableSet.copyOf( + Arrays.stream(containerClass.getDeclaredClasses()) + .filter( + innerClass -> clazz.isAssignableFrom(innerClass) + && !Modifier.isAbstract(innerClass.getModifiers())) + .collect(Collectors.toSet())); } static String methodToString(Executable executable) { @@ -611,9 +631,16 @@ public class NotificationVisitUrisTest extends UiServiceTestCase { } private static class SpecialParameterGenerator { + + private static final ImmutableSet<Class<?>> INTERESTING_CLASSES_WITH_SPECIAL_GENERATION = + ImmutableSet.of(Uri.class, Icon.class, Intent.class, PendingIntent.class, + RemoteViews.class); + private static final ImmutableSet<Class<?>> INTERESTING_CLASSES = - ImmutableSet.of(Person.class, Uri.class, Icon.class, Intent.class, - PendingIntent.class, RemoteViews.class); + new ImmutableSet.Builder<Class<?>>() + .addAll(INTERESTING_CLASSES_WITH_SPECIAL_GENERATION) + .add(Person.class) // Constructed via reflection, but high-score. + .build(); private static final ImmutableSet<Class<?>> MOCKED_CLASSES = ImmutableSet.of(); private static final ImmutableMap<Class<?>, Object> PRIMITIVE_VALUES = @@ -637,7 +664,7 @@ public class NotificationVisitUrisTest extends UiServiceTestCase { } static boolean canGenerate(Class<?> clazz) { - return INTERESTING_CLASSES.contains(clazz) + return INTERESTING_CLASSES_WITH_SPECIAL_GENERATION.contains(clazz) || MOCKED_CLASSES.contains(clazz) || clazz.equals(Context.class) || clazz.equals(Bundle.class) @@ -672,17 +699,6 @@ public class NotificationVisitUrisTest extends UiServiceTestCase { return Icon.createWithContentUri(iconUri); } - if (clazz == Person.class) { - // TODO(b/310189261): Person.setUri takes a string instead of a URI. We should - // find a way to use the SpecialParameterGenerator instead of this custom one. - Uri personUri = generateUri( - where.plus(Person.Builder.class).plus("setUri", String.class)); - Uri iconUri = generateUri(where.plus(Person.Builder.class).plus("setIcon", - Icon.class).plus(Icon.class).plus("createWithContentUri", Uri.class)); - return new Person.Builder().setUri(personUri.toString()).setIcon( - Icon.createWithContentUri(iconUri)).setName("John Doe").build(); - } - if (clazz == Intent.class) { return new Intent("action", generateUri(where.plus(Intent.class))); } 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 248683836336..25ad7dbac30c 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java @@ -59,6 +59,7 @@ import static android.service.notification.ZenModeConfig.UPDATE_ORIGIN_SYSTEM_OR import static android.service.notification.ZenModeConfig.UPDATE_ORIGIN_UNKNOWN; import static android.service.notification.ZenModeConfig.UPDATE_ORIGIN_USER; import static android.service.notification.ZenPolicy.PEOPLE_TYPE_CONTACTS; +import static android.service.notification.ZenPolicy.PEOPLE_TYPE_NONE; import static android.service.notification.ZenPolicy.PEOPLE_TYPE_STARRED; import static com.android.internal.config.sysui.SystemUiSystemPropertiesFlags.NotificationFlags.LOG_DND_STATE_EVENTS; @@ -123,6 +124,7 @@ import android.os.Parcel; import android.os.Process; import android.os.SimpleClock; import android.os.UserHandle; +import android.platform.test.annotations.DisableFlags; import android.platform.test.annotations.EnableFlags; import android.platform.test.flag.junit.SetFlagsRule; import android.provider.Settings; @@ -238,15 +240,19 @@ public class ZenModeHelperTest extends UiServiceTestCase { public TestWithLooperRule mLooperRule = new TestWithLooperRule(); ConditionProviders mConditionProviders; - @Mock NotificationManager mNotificationManager; - @Mock PackageManager mPackageManager; + @Mock + NotificationManager mNotificationManager; + @Mock + PackageManager mPackageManager; private Resources mResources; private TestableLooper mTestableLooper; private final TestClock mTestClock = new TestClock(); private ZenModeHelper mZenModeHelper; private ContentResolver mContentResolver; - @Mock DeviceEffectsApplier mDeviceEffectsApplier; - @Mock AppOpsManager mAppOps; + @Mock + DeviceEffectsApplier mDeviceEffectsApplier; + @Mock + AppOpsManager mAppOps; TestableFlagResolver mTestFlagResolver = new TestableFlagResolver(); ZenModeEventLoggerFake mZenModeEventLogger; @@ -290,7 +296,7 @@ public class ZenModeHelperTest extends UiServiceTestCase { when(mPackageManager.getPackageUidAsUser(eq(CUSTOM_PKG_NAME), anyInt())) .thenReturn(CUSTOM_PKG_UID); when(mPackageManager.getPackagesForUid(anyInt())).thenReturn( - new String[] {pkg}); + new String[]{pkg}); ApplicationInfo appInfoSpy = spy(new ApplicationInfo()); appInfoSpy.icon = ICON_RES_ID; @@ -305,24 +311,26 @@ public class ZenModeHelperTest extends UiServiceTestCase { } private XmlResourceParser getDefaultConfigParser() throws IOException, XmlPullParserException { - String xml = "<zen version=\"8\" user=\"0\">\n" - + "<allow calls=\"false\" repeatCallers=\"false\" messages=\"true\" " - + "reminders=\"false\" events=\"false\" callsFrom=\"1\" messagesFrom=\"2\" " - + "visualScreenOff=\"true\" alarms=\"true\" " - + "media=\"true\" system=\"false\" conversations=\"true\"" - + " conversationsFrom=\"2\"/>\n" - + "<automatic ruleId=\"" + EVENTS_DEFAULT_RULE_ID - + "\" enabled=\"false\" snoozing=\"false\"" - + " name=\"Event\" zen=\"1\"" - + " component=\"android/com.android.server.notification.EventConditionProvider\"" - + " conditionId=\"condition://android/event?userId=-10000&calendar=&" + String xml = "<zen version=\"10\">\n" + + "<allow alarms=\"true\" media=\"true\" system=\"false\" calls=\"true\" " + + "callsFrom=\"2\" messages=\"true\"\n" + + "messagesFrom=\"2\" reminders=\"false\" events=\"false\" " + + "repeatCallers=\"true\" convos=\"true\"\n" + + "convosFrom=\"2\"/>\n" + + "<automatic ruleId=" + EVENTS_DEFAULT_RULE_ID + + " enabled=\"false\" snoozing=\"false\"" + + " name=\"Event\" zen=\"1\"\n" + + " component=\"android/com.android.server.notification.EventConditionProvider\"\n" + + " conditionId=\"condition://android/event?userId=-10000&calendar=&" + "reply=1\"/>\n" - + "<automatic ruleId=\"" + SCHEDULE_DEFAULT_RULE_ID + "\" enabled=\"false\"" - + " snoozing=\"false\" name=\"Sleeping\" zen=\"1\"" - + " component=\"android/com.android.server.notification.ScheduleConditionProvider\"" - + " conditionId=\"condition://android/schedule?days=1.2.3.4.5.6.7 &start=22.0" - + "&end=7.0&exitAtAlarm=true\"/>" - + "<disallow visualEffects=\"511\" />" + + "<automatic ruleId=" + SCHEDULE_DEFAULT_RULE_ID + " enabled=\"false\"" + + " snoozing=\"false\" name=\"Sleeping\"\n zen=\"1\"" + + " component=\"android/com.android.server.notification" + + ".ScheduleConditionProvider\"\n" + + " conditionId=\"condition://android/schedule?days=1.2.3.4.5.6.7&start=22.0" + + "&end=7.0&exitAtAlarm=true\"/>\n" + + "<disallow visualEffects=\"157\" />\n" + + "<state areChannelsBypassingDnd=\"false\" />\n" + "</zen>"; TypedXmlPullParser parser = Xml.newFastPullParser(); parser.setInput(new BufferedInputStream(new ByteArrayInputStream(xml.getBytes())), null); @@ -408,7 +416,7 @@ public class ZenModeHelperTest extends UiServiceTestCase { @Test public void testZenOff_NoMuteApplied() { mZenModeHelper.mZenMode = ZEN_MODE_OFF; - mZenModeHelper.setPriorityOnlyDndExemptPackages(new String[] {PKG_O}); + mZenModeHelper.setPriorityOnlyDndExemptPackages(new String[]{PKG_O}); mZenModeHelper.mConsolidatedPolicy = new Policy(Policy.PRIORITY_CATEGORY_ALARMS | PRIORITY_CATEGORY_MEDIA, 0, 0, 0, 0, 0); mZenModeHelper.applyRestrictions(); @@ -421,7 +429,7 @@ public class ZenModeHelperTest extends UiServiceTestCase { @Test public void testZenOn_NotificationApplied() { mZenModeHelper.mZenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS; - mZenModeHelper.setPriorityOnlyDndExemptPackages(new String[] {PKG_O}); + mZenModeHelper.setPriorityOnlyDndExemptPackages(new String[]{PKG_O}); // The most permissive policy mZenModeHelper.mConsolidatedPolicy = new Policy(Policy.PRIORITY_CATEGORY_ALARMS | PRIORITY_CATEGORY_MEDIA | PRIORITY_CATEGORY_MESSAGES @@ -442,7 +450,7 @@ public class ZenModeHelperTest extends UiServiceTestCase { @Test public void testZenOn_StarredCallers_CallTypesBlocked() { mZenModeHelper.mZenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS; - mZenModeHelper.setPriorityOnlyDndExemptPackages(new String[] {PKG_O}); + mZenModeHelper.setPriorityOnlyDndExemptPackages(new String[]{PKG_O}); // The most permissive policy mZenModeHelper.mConsolidatedPolicy = new Policy(Policy.PRIORITY_CATEGORY_ALARMS | PRIORITY_CATEGORY_MEDIA | PRIORITY_CATEGORY_MESSAGES @@ -462,7 +470,7 @@ public class ZenModeHelperTest extends UiServiceTestCase { @Test public void testZenOn_AllCallers_CallTypesAllowed() { mZenModeHelper.mZenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS; - mZenModeHelper.setPriorityOnlyDndExemptPackages(new String[] {PKG_O}); + mZenModeHelper.setPriorityOnlyDndExemptPackages(new String[]{PKG_O}); // The most permissive policy mZenModeHelper.mConsolidatedPolicy = new Policy(Policy.PRIORITY_CATEGORY_ALARMS | PRIORITY_CATEGORY_MEDIA | PRIORITY_CATEGORY_MESSAGES @@ -481,7 +489,7 @@ public class ZenModeHelperTest extends UiServiceTestCase { @Test public void testZenOn_AllowAlarmsMedia_NoAlarmMediaMuteApplied() { mZenModeHelper.mZenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS; - mZenModeHelper.setPriorityOnlyDndExemptPackages(new String[] {PKG_O}); + mZenModeHelper.setPriorityOnlyDndExemptPackages(new String[]{PKG_O}); mZenModeHelper.mConsolidatedPolicy = new Policy(Policy.PRIORITY_CATEGORY_ALARMS | PRIORITY_CATEGORY_MEDIA, 0, 0, 0, 0, 0); @@ -493,7 +501,7 @@ public class ZenModeHelperTest extends UiServiceTestCase { @Test public void testZenOn_DisallowAlarmsMedia_AlarmMediaMuteApplied() { mZenModeHelper.mZenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS; - mZenModeHelper.setPriorityOnlyDndExemptPackages(new String[] {PKG_O}); + mZenModeHelper.setPriorityOnlyDndExemptPackages(new String[]{PKG_O}); mZenModeHelper.mConsolidatedPolicy = new Policy(0, 0, 0, 0, 0, 0); mZenModeHelper.applyRestrictions(); verifyApplyRestrictions(true, true, AudioAttributes.USAGE_ALARM); @@ -506,7 +514,7 @@ public class ZenModeHelperTest extends UiServiceTestCase { @Test public void testTotalSilence() { mZenModeHelper.mZenMode = Settings.Global.ZEN_MODE_NO_INTERRUPTIONS; - mZenModeHelper.setPriorityOnlyDndExemptPackages(new String[] {PKG_O}); + mZenModeHelper.setPriorityOnlyDndExemptPackages(new String[]{PKG_O}); mZenModeHelper.mConsolidatedPolicy = new Policy(Policy.PRIORITY_CATEGORY_ALARMS | PRIORITY_CATEGORY_MEDIA, 0, 0, 0, 0, 0); mZenModeHelper.applyRestrictions(); @@ -525,7 +533,7 @@ public class ZenModeHelperTest extends UiServiceTestCase { @Test public void testAlarmsOnly_alarmMediaMuteNotApplied() { mZenModeHelper.mZenMode = Settings.Global.ZEN_MODE_ALARMS; - mZenModeHelper.setPriorityOnlyDndExemptPackages(new String[] {PKG_O}); + mZenModeHelper.setPriorityOnlyDndExemptPackages(new String[]{PKG_O}); mZenModeHelper.mConsolidatedPolicy = new Policy(0, 0, 0, 0, 0, 0); mZenModeHelper.applyRestrictions(); @@ -545,7 +553,7 @@ public class ZenModeHelperTest extends UiServiceTestCase { @Test public void testAlarmsOnly_callsMuteApplied() { mZenModeHelper.mZenMode = Settings.Global.ZEN_MODE_ALARMS; - mZenModeHelper.setPriorityOnlyDndExemptPackages(new String[] {PKG_O}); + mZenModeHelper.setPriorityOnlyDndExemptPackages(new String[]{PKG_O}); mZenModeHelper.mConsolidatedPolicy = new Policy(0, 0, 0, 0, 0, 0); mZenModeHelper.applyRestrictions(); @@ -559,7 +567,7 @@ public class ZenModeHelperTest extends UiServiceTestCase { public void testAlarmsOnly_allZenConfigToggledCannotBypass_alarmMuteNotApplied() { // Only audio attributes with SUPPRESIBLE_NEVER can bypass mZenModeHelper.mZenMode = Settings.Global.ZEN_MODE_ALARMS; - mZenModeHelper.setPriorityOnlyDndExemptPackages(new String[] {PKG_O}); + mZenModeHelper.setPriorityOnlyDndExemptPackages(new String[]{PKG_O}); mZenModeHelper.mConsolidatedPolicy = new Policy(0, 0, 0, 0, 0, 0); mZenModeHelper.applyRestrictions(); @@ -571,7 +579,7 @@ public class ZenModeHelperTest extends UiServiceTestCase { // Only audio attributes with SUPPRESIBLE_NEVER can bypass // with special case USAGE_ASSISTANCE_SONIFICATION mZenModeHelper.mZenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS; - mZenModeHelper.setPriorityOnlyDndExemptPackages(new String[] {PKG_O}); + mZenModeHelper.setPriorityOnlyDndExemptPackages(new String[]{PKG_O}); mZenModeHelper.mConsolidatedPolicy = new Policy(0, 0, 0, 0, 0, 0); mZenModeHelper.applyRestrictions(); @@ -592,7 +600,7 @@ public class ZenModeHelperTest extends UiServiceTestCase { @Test public void testApplyRestrictions_whitelist_priorityOnlyMode() { - mZenModeHelper.setPriorityOnlyDndExemptPackages(new String[] {PKG_O}); + mZenModeHelper.setPriorityOnlyDndExemptPackages(new String[]{PKG_O}); mZenModeHelper.mZenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS; mZenModeHelper.mConsolidatedPolicy = new Policy(0, 0, 0, 0, 0, 0); mZenModeHelper.applyRestrictions(); @@ -607,7 +615,7 @@ public class ZenModeHelperTest extends UiServiceTestCase { @Test public void testApplyRestrictions_whitelist_alarmsOnlyMode() { - mZenModeHelper.setPriorityOnlyDndExemptPackages(new String[] {PKG_O}); + mZenModeHelper.setPriorityOnlyDndExemptPackages(new String[]{PKG_O}); mZenModeHelper.mZenMode = Global.ZEN_MODE_ALARMS; mZenModeHelper.mConsolidatedPolicy = new Policy(0, 0, 0, 0, 0, 0); mZenModeHelper.applyRestrictions(); @@ -622,7 +630,7 @@ public class ZenModeHelperTest extends UiServiceTestCase { @Test public void testApplyRestrictions_whitelist_totalSilenceMode() { - mZenModeHelper.setPriorityOnlyDndExemptPackages(new String[] {PKG_O}); + mZenModeHelper.setPriorityOnlyDndExemptPackages(new String[]{PKG_O}); mZenModeHelper.mZenMode = Global.ZEN_MODE_NO_INTERRUPTIONS; mZenModeHelper.mConsolidatedPolicy = new Policy(0, 0, 0, 0, 0, 0); mZenModeHelper.applyRestrictions(); @@ -1007,7 +1015,7 @@ public class ZenModeHelperTest extends UiServiceTestCase { mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL); assertEquals("Config mismatch: current vs expected: " - + new ZenModeDiff.ConfigDiff(mZenModeHelper.mConfig, expected), expected, + + new ZenModeDiff.ConfigDiff(mZenModeHelper.mConfig, expected), expected, mZenModeHelper.mConfig); } @@ -1336,7 +1344,7 @@ public class ZenModeHelperTest extends UiServiceTestCase { mZenModeHelper.readXml(parser, true, UserHandle.USER_SYSTEM); assertEquals("Config mismatch: current vs original: " - + new ZenModeDiff.ConfigDiff(mZenModeHelper.mConfig, original), + + new ZenModeDiff.ConfigDiff(mZenModeHelper.mConfig, original), original, mZenModeHelper.mConfig); assertEquals(original.hashCode(), mZenModeHelper.mConfig.hashCode()); } @@ -1778,6 +1786,225 @@ public class ZenModeHelperTest extends UiServiceTestCase { } @Test + @EnableFlags(Flags.FLAG_MODES_API) + public void testReadXml_onModesApi_noUpgrade() throws Exception { + // When reading XML for something that is already on the modes API system, make sure no + // rules' policies get changed. + setupZenConfig(); + + // Shared for rules + ArrayMap<String, ZenModeConfig.ZenRule> enabledAutoRules = new ArrayMap<>(); + final ScheduleInfo weeknights = new ScheduleInfo(); + + // Custom rule with a custom policy + ZenModeConfig.ZenRule customRule = new ZenModeConfig.ZenRule(); + customRule.enabled = true; + customRule.name = "Custom Rule"; + customRule.zenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS; + customRule.conditionId = ZenModeConfig.toScheduleConditionId(weeknights); + customRule.component = new ComponentName("android", "ScheduleConditionProvider"); + ZenPolicy policy = new ZenPolicy.Builder() + .allowCalls(PEOPLE_TYPE_CONTACTS) + .allowAlarms(true) + .allowRepeatCallers(false) + .build(); + // Fill in policy fields, since on modes api we do not expect any rules to have unset fields + customRule.zenPolicy = mZenModeHelper.getDefaultZenPolicy().overwrittenWith(policy); + enabledAutoRules.put("customRule", customRule); + mZenModeHelper.mConfig.automaticRules = enabledAutoRules; + + // set version to post-modes-API = 11 + ByteArrayOutputStream baos = writeXmlAndPurge(11); + TypedXmlPullParser parser = Xml.newFastPullParser(); + parser.setInput(new BufferedInputStream( + new ByteArrayInputStream(baos.toByteArray())), null); + parser.nextTag(); + mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL); + + // basic check: global config maintained + setupZenConfigMaintained(); + + // Find our automatic rules. + ArrayMap<String, ZenModeConfig.ZenRule> rules = mZenModeHelper.mConfig.automaticRules; + assertThat(rules).hasSize(1); + assertThat(rules).containsKey("customRule"); + ZenRule rule = rules.get("customRule"); + assertThat(rule.zenPolicy).isEqualTo(customRule.zenPolicy); + } + + @Test + @EnableFlags(Flags.FLAG_MODES_API) + public void testReadXml_upgradeToModesApi_makesCustomPolicies() throws Exception { + // When reading in an XML file written from a pre-modes-API version, confirm that we create + // a custom policy matching the global config for any automatic rule with no specified + // policy. + setupZenConfig(); + + ArrayMap<String, ZenModeConfig.ZenRule> enabledAutoRule = new ArrayMap<>(); + ZenModeConfig.ZenRule customRule = new ZenModeConfig.ZenRule(); + final ScheduleInfo weeknights = new ScheduleInfo(); + customRule.enabled = true; + customRule.name = "Custom Rule"; + customRule.zenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS; + customRule.conditionId = ZenModeConfig.toScheduleConditionId(weeknights); + customRule.component = new ComponentName("android", "ScheduleConditionProvider"); + enabledAutoRule.put("customRule", customRule); // no custom policy set + mZenModeHelper.mConfig.automaticRules = enabledAutoRule; + + // set version to pre-modes-API = 10 + ByteArrayOutputStream baos = writeXmlAndPurge(10); + TypedXmlPullParser parser = Xml.newFastPullParser(); + parser.setInput(new BufferedInputStream( + new ByteArrayInputStream(baos.toByteArray())), null); + parser.nextTag(); + mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL); + + // basic check: global config maintained + setupZenConfigMaintained(); + + // Find our automatic rule and check that it has a policy set now + ArrayMap<String, ZenModeConfig.ZenRule> rules = mZenModeHelper.mConfig.automaticRules; + assertThat(rules).hasSize(1); + assertThat(rules).containsKey("customRule"); + ZenRule rule = rules.get("customRule"); + assertThat(rule.zenPolicy).isNotNull(); + + // Check policy values as set up in setupZenConfig() to confirm they match + assertThat(rule.zenPolicy.getPriorityCategoryAlarms()).isEqualTo(STATE_DISALLOW); + assertThat(rule.zenPolicy.getPriorityCategoryMedia()).isEqualTo(STATE_DISALLOW); + assertThat(rule.zenPolicy.getPriorityCategorySystem()).isEqualTo(STATE_DISALLOW); + assertThat(rule.zenPolicy.getPriorityCategoryReminders()).isEqualTo(STATE_ALLOW); + assertThat(rule.zenPolicy.getPriorityCategoryCalls()).isEqualTo(STATE_ALLOW); + assertThat(rule.zenPolicy.getPriorityCallSenders()).isEqualTo(PEOPLE_TYPE_STARRED); + assertThat(rule.zenPolicy.getPriorityCategoryMessages()).isEqualTo(STATE_ALLOW); + assertThat(rule.zenPolicy.getPriorityCategoryConversations()).isEqualTo(STATE_ALLOW); + assertThat(rule.zenPolicy.getPriorityCategoryEvents()).isEqualTo(STATE_ALLOW); + assertThat(rule.zenPolicy.getPriorityCategoryRepeatCallers()).isEqualTo(STATE_ALLOW); + assertThat(rule.zenPolicy.getVisualEffectBadge()).isEqualTo(STATE_DISALLOW); + } + + @Test + @EnableFlags(Flags.FLAG_MODES_API) + public void testReadXml_upgradeToModesApi_fillsInCustomPolicies() throws Exception { + // When reading in an XML file written from a pre-modes-API version, confirm that for an + // underspecified ZenPolicy, we fill in all of the gaps with things from the global config + // in order to maintain consistency of behavior. + setupZenConfig(); + + ArrayMap<String, ZenModeConfig.ZenRule> enabledAutoRule = new ArrayMap<>(); + ZenModeConfig.ZenRule customRule = new ZenModeConfig.ZenRule(); + final ScheduleInfo weeknights = new ScheduleInfo(); + customRule.enabled = true; + customRule.name = "Custom Rule"; + customRule.zenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS; + customRule.conditionId = ZenModeConfig.toScheduleConditionId(weeknights); + customRule.component = new ComponentName("android", "ScheduleConditionProvider"); + customRule.zenPolicy = new ZenPolicy.Builder() + .allowAlarms(true) + .allowMedia(true) + .allowRepeatCallers(false) + .build(); + enabledAutoRule.put("customRule", customRule); + mZenModeHelper.mConfig.automaticRules = enabledAutoRule; + + // set version to pre-modes-API = 10 + ByteArrayOutputStream baos = writeXmlAndPurge(10); + TypedXmlPullParser parser = Xml.newFastPullParser(); + parser.setInput(new BufferedInputStream( + new ByteArrayInputStream(baos.toByteArray())), null); + parser.nextTag(); + mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL); + + // basic check: global config maintained + setupZenConfigMaintained(); + + // Find our automatic rule and check that it has a policy set now + ArrayMap<String, ZenModeConfig.ZenRule> rules = mZenModeHelper.mConfig.automaticRules; + assertThat(rules).hasSize(1); + assertThat(rules).containsKey("customRule"); + ZenRule rule = rules.get("customRule"); + assertThat(rule.zenPolicy).isNotNull(); + + // Check unset policy values match values in setupZenConfig(). + // Check that set policy values match the values set in the policy. + assertThat(rule.zenPolicy.getPriorityCategoryAlarms()).isEqualTo(STATE_ALLOW); + assertThat(rule.zenPolicy.getPriorityCategoryMedia()).isEqualTo(STATE_ALLOW); + assertThat(rule.zenPolicy.getPriorityCategoryRepeatCallers()).isEqualTo(STATE_DISALLOW); + + // Check that the rest is filled in from the default + assertThat(rule.zenPolicy.getPriorityCategorySystem()).isEqualTo(STATE_DISALLOW); + assertThat(rule.zenPolicy.getPriorityCategoryReminders()).isEqualTo(STATE_ALLOW); + assertThat(rule.zenPolicy.getPriorityCategoryCalls()).isEqualTo(STATE_ALLOW); + assertThat(rule.zenPolicy.getPriorityCallSenders()).isEqualTo(PEOPLE_TYPE_STARRED); + assertThat(rule.zenPolicy.getPriorityCategoryMessages()).isEqualTo(STATE_ALLOW); + assertThat(rule.zenPolicy.getPriorityCategoryConversations()).isEqualTo(STATE_ALLOW); + assertThat(rule.zenPolicy.getPriorityCategoryEvents()).isEqualTo(STATE_ALLOW); + assertThat(rule.zenPolicy.getVisualEffectBadge()).isEqualTo(STATE_DISALLOW); + } + + @Test + @EnableFlags(Flags.FLAG_MODES_API) + public void testReadXml_upgradeToModesApi_existingDefaultRulesGetCustomPolicy() + throws Exception { + setupZenConfig(); + + // Default rules, if they exist and have no policies, should get a snapshot of the global + // policy, even if they are disabled upon upgrade. + ArrayMap<String, ZenModeConfig.ZenRule> automaticRules = new ArrayMap<>(); + ZenModeConfig.ZenRule defaultScheduleRule = new ZenModeConfig.ZenRule(); + final ScheduleInfo defaultScheduleRuleInfo = new ScheduleInfo(); + defaultScheduleRule.enabled = false; + defaultScheduleRule.name = "Default Schedule Rule"; + defaultScheduleRule.zenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS; + defaultScheduleRule.conditionId = ZenModeConfig.toScheduleConditionId( + defaultScheduleRuleInfo); + defaultScheduleRule.id = ZenModeConfig.EVERY_NIGHT_DEFAULT_RULE_ID; + automaticRules.put(ZenModeConfig.EVERY_NIGHT_DEFAULT_RULE_ID, defaultScheduleRule); + + ZenModeConfig.ZenRule defaultEventRule = new ZenModeConfig.ZenRule(); + final ScheduleInfo defaultEventRuleInfo = new ScheduleInfo(); + defaultEventRule.enabled = false; + defaultEventRule.name = "Default Event Rule"; + defaultEventRule.zenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS; + defaultEventRule.conditionId = ZenModeConfig.toScheduleConditionId( + defaultEventRuleInfo); + defaultEventRule.id = ZenModeConfig.EVENTS_DEFAULT_RULE_ID; + automaticRules.put(ZenModeConfig.EVENTS_DEFAULT_RULE_ID, defaultEventRule); + + mZenModeHelper.mConfig.automaticRules = automaticRules; + + // set previous version + ByteArrayOutputStream baos = writeXmlAndPurge(10); + TypedXmlPullParser parser = Xml.newFastPullParser(); + parser.setInput(new BufferedInputStream( + new ByteArrayInputStream(baos.toByteArray())), null); + parser.nextTag(); + mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL); + + // check default rules + ArrayMap<String, ZenModeConfig.ZenRule> rules = mZenModeHelper.mConfig.automaticRules; + assertThat(rules.size()).isGreaterThan(0); + for (String defaultId : ZenModeConfig.DEFAULT_RULE_IDS) { + assertThat(rules).containsKey(defaultId); + ZenRule rule = rules.get(defaultId); + assertThat(rule.zenPolicy).isNotNull(); + + // Check policy values as set up in setupZenConfig() to confirm they match + assertThat(rule.zenPolicy.getPriorityCategoryAlarms()).isEqualTo(STATE_DISALLOW); + assertThat(rule.zenPolicy.getPriorityCategoryMedia()).isEqualTo(STATE_DISALLOW); + assertThat(rule.zenPolicy.getPriorityCategorySystem()).isEqualTo(STATE_DISALLOW); + assertThat(rule.zenPolicy.getPriorityCategoryReminders()).isEqualTo(STATE_ALLOW); + assertThat(rule.zenPolicy.getPriorityCategoryCalls()).isEqualTo(STATE_ALLOW); + assertThat(rule.zenPolicy.getPriorityCallSenders()).isEqualTo(PEOPLE_TYPE_STARRED); + assertThat(rule.zenPolicy.getPriorityCategoryMessages()).isEqualTo(STATE_ALLOW); + assertThat(rule.zenPolicy.getPriorityCategoryConversations()).isEqualTo(STATE_ALLOW); + assertThat(rule.zenPolicy.getPriorityCategoryEvents()).isEqualTo(STATE_ALLOW); + assertThat(rule.zenPolicy.getPriorityCategoryRepeatCallers()).isEqualTo(STATE_ALLOW); + assertThat(rule.zenPolicy.getVisualEffectBadge()).isEqualTo(STATE_DISALLOW); + } + } + + @Test public void testCountdownConditionSubscription() throws Exception { ZenModeConfig config = new ZenModeConfig(); mZenModeHelper.mConfig = config; @@ -2036,6 +2263,69 @@ public class ZenModeHelperTest extends UiServiceTestCase { } @Test + @EnableFlags(Flags.FLAG_MODES_API) + public void testAddAutomaticZenRule_modesApi_fillsInDefaultValues() { + // When a new automatic zen rule is added with only some fields filled in, ensure that + // all unset fields are filled in with device defaults. + + // Zen rule with null policy: should get entirely the default state + AutomaticZenRule zenRule1 = new AutomaticZenRule("name", + new ComponentName("android", "ScheduleConditionProvider"), + ZenModeConfig.toScheduleConditionId(new ScheduleInfo()), + NotificationManager.INTERRUPTION_FILTER_PRIORITY, true); + String id1 = mZenModeHelper.addAutomaticZenRule("android", zenRule1, + UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "test", Process.SYSTEM_UID); + + // Zen rule with partially-filled policy: should get all of the filled fields set, and the + // rest filled with default state + AutomaticZenRule zenRule2 = new AutomaticZenRule("name", + null, + new ComponentName(mContext.getPackageName(), "ScheduleConditionProvider"), + ZenModeConfig.toScheduleConditionId(new ScheduleInfo()), + new ZenPolicy.Builder() + .allowCalls(PEOPLE_TYPE_NONE) + .allowMessages(PEOPLE_TYPE_CONTACTS) + .showFullScreenIntent(true) + .build(), + NotificationManager.INTERRUPTION_FILTER_PRIORITY, true); + String id2 = mZenModeHelper.addAutomaticZenRule("android", zenRule2, + UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "test", Process.SYSTEM_UID); + + // rule 1 should exist + assertThat(id1).isNotNull(); + ZenModeConfig.ZenRule rule1InConfig = mZenModeHelper.mConfig.automaticRules.get(id1); + assertThat(rule1InConfig).isNotNull(); + assertThat(rule1InConfig.zenPolicy).isNotNull(); // we passed in null; it should now not be + + // all of rule 1 should be the device default's policy + assertThat(rule1InConfig.zenPolicy).isEqualTo(mZenModeHelper.getDefaultZenPolicy()); + + // rule 2 should exist + assertThat(id2).isNotNull(); + ZenModeConfig.ZenRule rule2InConfig = mZenModeHelper.mConfig.automaticRules.get(id2); + assertThat(rule2InConfig).isNotNull(); + + // rule 2: values set from the policy itself + assertThat(rule2InConfig.zenPolicy.getPriorityCallSenders()).isEqualTo(PEOPLE_TYPE_NONE); + assertThat(rule2InConfig.zenPolicy.getPriorityMessageSenders()) + .isEqualTo(PEOPLE_TYPE_CONTACTS); + assertThat(rule2InConfig.zenPolicy.getVisualEffectFullScreenIntent()) + .isEqualTo(ZenPolicy.STATE_ALLOW); + + // the rest of rule 2's settings should be the device defaults + assertThat(rule2InConfig.zenPolicy.getPriorityConversationSenders()) + .isEqualTo(CONVERSATION_SENDERS_IMPORTANT); + assertThat(rule2InConfig.zenPolicy.getPriorityCategorySystem()) + .isEqualTo(ZenPolicy.STATE_DISALLOW); + assertThat(rule2InConfig.zenPolicy.getPriorityCategoryAlarms()) + .isEqualTo(ZenPolicy.STATE_ALLOW); + assertThat(rule2InConfig.zenPolicy.getVisualEffectPeek()) + .isEqualTo(ZenPolicy.STATE_DISALLOW); + assertThat(rule2InConfig.zenPolicy.getVisualEffectNotificationList()) + .isEqualTo(ZenPolicy.STATE_ALLOW); + } + + @Test public void testSetAutomaticZenRuleState_nullPkg() { AutomaticZenRule zenRule = new AutomaticZenRule("name", null, @@ -2357,6 +2647,68 @@ public class ZenModeHelperTest extends UiServiceTestCase { @Test @EnableFlags(Flags.FLAG_MODES_API) + public void updateAutomaticZenRule_nullPolicy_doesNothing() { + // Test that when updateAutomaticZenRule is called with a null policy, nothing changes + // about the existing policy. + String ruleId = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), + new AutomaticZenRule.Builder("Rule", CONDITION_ID) + .setOwner(OWNER) + .setZenPolicy(new ZenPolicy.Builder() + .allowCalls(ZenPolicy.PEOPLE_TYPE_NONE) // default is stars + .build()) + .build(), + UPDATE_ORIGIN_APP, "reasons", 0); + + mZenModeHelper.updateAutomaticZenRule(ruleId, + new AutomaticZenRule.Builder("Rule", CONDITION_ID) + // no zen policy + .build(), + UPDATE_ORIGIN_APP, "reasons", 0); + + AutomaticZenRule savedRule = mZenModeHelper.getAutomaticZenRule(ruleId); + assertThat(savedRule.getZenPolicy().getPriorityCategoryCalls()) + .isEqualTo(ZenPolicy.STATE_DISALLOW); + } + + @Test + @EnableFlags(Flags.FLAG_MODES_API) + public void updateAutomaticZenRule_overwritesExistingPolicy() { + // Test that when updating an automatic zen rule with an existing policy, the newly set + // fields overwrite those from the previous policy, but unset fields in the new policy + // keep values from the previous one. + String ruleId = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), + new AutomaticZenRule.Builder("Rule", CONDITION_ID) + .setOwner(OWNER) + .setZenPolicy(new ZenPolicy.Builder() + .allowCalls(ZenPolicy.PEOPLE_TYPE_NONE) // default is stars + .allowAlarms(false) + .allowReminders(true) + .build()) + .build(), + UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "reasons", 0); + + mZenModeHelper.updateAutomaticZenRule(ruleId, + new AutomaticZenRule.Builder("Rule", CONDITION_ID) + .setZenPolicy(new ZenPolicy.Builder() + .allowCalls(ZenPolicy.PEOPLE_TYPE_CONTACTS) + .build()) + .build(), + UPDATE_ORIGIN_APP, "reasons", 0); + + AutomaticZenRule savedRule = mZenModeHelper.getAutomaticZenRule(ruleId); + assertThat(savedRule.getZenPolicy().getPriorityCategoryCalls()) + .isEqualTo(ZenPolicy.STATE_ALLOW); // from update + assertThat(savedRule.getZenPolicy().getPriorityCallSenders()) + .isEqualTo(ZenPolicy.PEOPLE_TYPE_CONTACTS); // from update + assertThat(savedRule.getZenPolicy().getPriorityCategoryAlarms()) + .isEqualTo(ZenPolicy.STATE_DISALLOW); // from original + assertThat(savedRule.getZenPolicy().getPriorityCategoryReminders()) + .isEqualTo(ZenPolicy.STATE_ALLOW); // from original + } + + + @Test + @EnableFlags(Flags.FLAG_MODES_API) public void addAutomaticZenRule_withTypeBedtime_replacesDisabledSleeping() { ZenRule sleepingRule = createCustomAutomaticRule(ZEN_MODE_IMPORTANT_INTERRUPTIONS, ZenModeConfig.EVERY_NIGHT_DEFAULT_RULE_ID); @@ -2460,7 +2812,8 @@ public class ZenModeHelperTest extends UiServiceTestCase { DISABLED(false, /* originForUserActionInSystemUi= */ UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI); private final boolean mEnabled; - @ConfigChangeOrigin private final int mOriginForUserActionInSystemUi; + @ConfigChangeOrigin + private final int mOriginForUserActionInSystemUi; ModesApiFlag(boolean enabled, @ConfigChangeOrigin int originForUserActionInSystemUi) { this.mEnabled = enabled; @@ -2506,7 +2859,7 @@ public class ZenModeHelperTest extends UiServiceTestCase { // - rules active = 1 // - user action = true (system-based turning zen mode on) // - package uid = system (as set above) - // - resulting DNDPolicyProto the same as the values in setupZenConfig() + // - resulting DNDPolicyProto the same as the values in setupZenConfig() (global policy) assertEquals(ZenModeEventLogger.ZenStateChangedEvent.DND_TURNED_ON.getId(), mZenModeEventLogger.getEventId(0)); assertEquals(ZEN_MODE_OFF, mZenModeEventLogger.getPrevZenMode(0)); @@ -2600,7 +2953,7 @@ public class ZenModeHelperTest extends UiServiceTestCase { // - 1 rule (newly) active // - automatic (is not a user action) // - package UID is written to be the rule *owner* even though it "comes from system" - // - zen policy is the same as the set-up zen config + // - zen policy is the default as it's unspecified assertEquals(ZenModeEventLogger.ZenStateChangedEvent.DND_TURNED_ON.getId(), mZenModeEventLogger.getEventId(0)); assertEquals(ZEN_MODE_OFF, mZenModeEventLogger.getPrevZenMode(0)); @@ -2609,10 +2962,10 @@ public class ZenModeHelperTest extends UiServiceTestCase { assertEquals(1, mZenModeEventLogger.getNumRulesActive(0)); assertFalse(mZenModeEventLogger.getIsUserAction(0)); assertEquals(CUSTOM_PKG_UID, mZenModeEventLogger.getPackageUid(0)); - checkDndProtoMatchesSetupZenConfig(mZenModeEventLogger.getPolicyProto(0)); + checkDndProtoMatchesDefaultZenConfig(mZenModeEventLogger.getPolicyProto(0)); // When the automatic rule is disabled, this should turn off zen mode and also count as a - // user action. + // user action. We don't care what the consolidated policy is when DND turns off. assertEquals(ZenModeEventLogger.ZenStateChangedEvent.DND_TURNED_OFF.getId(), mZenModeEventLogger.getEventId(1)); assertEquals(ZEN_MODE_IMPORTANT_INTERRUPTIONS, mZenModeEventLogger.getPrevZenMode(1)); @@ -2835,28 +3188,28 @@ public class ZenModeHelperTest extends UiServiceTestCase { // First: turn on rule 1 mZenModeHelper.setAutomaticZenRuleState(id, new Condition(zenRule.getConditionId(), "", STATE_TRUE), - UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, Process.SYSTEM_UID); + UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, Process.SYSTEM_UID); // Second: turn on rule 2 mZenModeHelper.setAutomaticZenRuleState(id2, new Condition(zenRule2.getConditionId(), "", STATE_TRUE), - UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, Process.SYSTEM_UID); + UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, Process.SYSTEM_UID); // Third: turn on rule 3 mZenModeHelper.setAutomaticZenRuleState(id3, new Condition(zenRule3.getConditionId(), "", STATE_TRUE), - UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, Process.SYSTEM_UID); + UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, Process.SYSTEM_UID); // Fourth: Turn *off* rule 2 mZenModeHelper.setAutomaticZenRuleState(id2, new Condition(zenRule2.getConditionId(), "", STATE_FALSE), - UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, Process.SYSTEM_UID); + UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, Process.SYSTEM_UID); // This should result in a total of four events assertEquals(4, mZenModeEventLogger.numLoggedChanges()); // Event 1: rule 1 turns on. We expect this to turn on DND (zen mode) overall, so that's - // what the event should reflect. At this time, the policy is the same as initial setup. + // what the event should reflect. At this time, the policy is the default. assertEquals(ZenModeEventLogger.ZenStateChangedEvent.DND_TURNED_ON.getId(), mZenModeEventLogger.getEventId(0)); assertEquals(ZEN_MODE_OFF, mZenModeEventLogger.getPrevZenMode(0)); @@ -2864,7 +3217,7 @@ public class ZenModeHelperTest extends UiServiceTestCase { assertEquals(1, mZenModeEventLogger.getNumRulesActive(0)); assertFalse(mZenModeEventLogger.getIsUserAction(0)); assertEquals(CUSTOM_PKG_UID, mZenModeEventLogger.getPackageUid(0)); - checkDndProtoMatchesSetupZenConfig(mZenModeEventLogger.getPolicyProto(0)); + checkDndProtoMatchesDefaultZenConfig(mZenModeEventLogger.getPolicyProto(0)); // Event 2: rule 2 turns on. This should not change anything about the policy, so the only // change is that there are more rules active now. @@ -2873,7 +3226,7 @@ public class ZenModeHelperTest extends UiServiceTestCase { assertEquals(2, mZenModeEventLogger.getNumRulesActive(1)); assertFalse(mZenModeEventLogger.getIsUserAction(1)); assertEquals(CUSTOM_PKG_UID, mZenModeEventLogger.getPackageUid(1)); - checkDndProtoMatchesSetupZenConfig(mZenModeEventLogger.getPolicyProto(1)); + checkDndProtoMatchesDefaultZenConfig(mZenModeEventLogger.getPolicyProto(1)); // Event 3: rule 3 turns on. This should trigger a policy change, and be classified as such, // but meanwhile also change the number of active rules. @@ -2926,12 +3279,16 @@ public class ZenModeHelperTest extends UiServiceTestCase { mTestFlagResolver.setFlagOverride(LOG_DND_STATE_EVENTS, true); setupZenConfig(); + // Explicitly set up all rules with the same policy as the manual rule so there will be + // no policy changes in this test case. + ZenPolicy manualRulePolicy = mZenModeHelper.mConfig.toZenPolicy(); + // Rule 1, owned by a package AutomaticZenRule zenRule = new AutomaticZenRule("name", null, new ComponentName(CUSTOM_PKG_NAME, "ScheduleConditionProvider"), ZenModeConfig.toScheduleConditionId(new ScheduleInfo()), - null, + manualRulePolicy, NotificationManager.INTERRUPTION_FILTER_PRIORITY, true); String id = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), zenRule, UPDATE_ORIGIN_APP, "test", Process.SYSTEM_UID); @@ -2941,7 +3298,7 @@ public class ZenModeHelperTest extends UiServiceTestCase { null, new ComponentName("android", "ScheduleConditionProvider"), ZenModeConfig.toScheduleConditionId(new ScheduleInfo()), - null, + manualRulePolicy, NotificationManager.INTERRUPTION_FILTER_PRIORITY, true); String id2 = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), zenRule2, modesApiFlag.mOriginForUserActionInSystemUi, "test", Process.SYSTEM_UID); @@ -3172,7 +3529,8 @@ public class ZenModeHelperTest extends UiServiceTestCase { } @Test - public void testUpdateConsolidatedPolicy_defaultRulesOnly() { + @DisableFlags(Flags.FLAG_MODES_API) + public void testUpdateConsolidatedPolicy_preModesApiDefaultRulesOnly_takesGlobalDefault() { setupZenConfig(); // When there's one automatic rule active and it doesn't specify a policy, test that the @@ -3205,12 +3563,39 @@ public class ZenModeHelperTest extends UiServiceTestCase { } @Test - public void testUpdateConsolidatedPolicy_customPolicyOnly() { + @EnableFlags(Flags.FLAG_MODES_API) + public void testUpdateConsolidatedPolicy_modesApiDefaultRulesOnly_takesDeviceDefault() { + setupZenConfig(); + + // When there's one automatic rule active and it doesn't specify a policy, test that the + // resulting consolidated policy is one that matches the default *device* settings. + AutomaticZenRule zenRule = new AutomaticZenRule("name", + null, + new ComponentName(CUSTOM_PKG_NAME, "ScheduleConditionProvider"), + ZenModeConfig.toScheduleConditionId(new ScheduleInfo()), + null, // null policy + NotificationManager.INTERRUPTION_FILTER_PRIORITY, true); + String id = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), zenRule, + UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "test", Process.SYSTEM_UID); + + // enable the rule + mZenModeHelper.setAutomaticZenRuleState(id, + new Condition(zenRule.getConditionId(), "", STATE_TRUE), + UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, Process.SYSTEM_UID); + + // inspect the consolidated policy, which should match the device default settings. + assertThat(ZenAdapters.notificationPolicyToZenPolicy(mZenModeHelper.mConsolidatedPolicy)) + .isEqualTo(mZenModeHelper.getDefaultZenPolicy()); + } + + @Test + @DisableFlags(Flags.FLAG_MODES_API) + public void testUpdateConsolidatedPolicy_preModesApiCustomPolicyOnly_fillInWithGlobal() { setupZenConfig(); // when there's only one automatic rule active and it has a custom policy, make sure that's - // what the consolidated policy reflects whether or not it's stricter than what the default - // would specify. + // what the consolidated policy reflects whether or not it's stricter than what the global + // config would specify. ZenPolicy customPolicy = new ZenPolicy.Builder() .allowAlarms(true) // more lenient than default .allowMedia(true) // more lenient than default @@ -3249,7 +3634,51 @@ public class ZenModeHelperTest extends UiServiceTestCase { } @Test - public void testUpdateConsolidatedPolicy_defaultAndCustomActive() { + @EnableFlags(Flags.FLAG_MODES_API) + public void testUpdateConsolidatedPolicy_modesApiCustomPolicyOnly_fillInWithDeviceDefault() { + setupZenConfig(); + + // when there's only one automatic rule active and it has a custom policy, make sure that's + // what the consolidated policy reflects whether or not it's stricter than what the default + // would specify. + ZenPolicy customPolicy = new ZenPolicy.Builder() + .allowSystem(true) // more lenient than default + .allowRepeatCallers(false) // more restrictive than default + .allowCalls(ZenPolicy.PEOPLE_TYPE_NONE) // more restrictive than default + .showFullScreenIntent(true) // more lenient + .showBadges(false) // more restrictive + .build(); + + AutomaticZenRule zenRule = new AutomaticZenRule("name", + null, + new ComponentName(CUSTOM_PKG_NAME, "ScheduleConditionProvider"), + ZenModeConfig.toScheduleConditionId(new ScheduleInfo()), + customPolicy, + NotificationManager.INTERRUPTION_FILTER_PRIORITY, true); + String id = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), zenRule, + UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "test", Process.SYSTEM_UID); + + // enable the rule; this will update the consolidated policy + mZenModeHelper.setAutomaticZenRuleState(id, + new Condition(zenRule.getConditionId(), "", STATE_TRUE), + UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, Process.SYSTEM_UID); + + // since this is the only active rule, the consolidated policy should match the custom + // policy for every field specified, and take default values for unspecified things + assertThat(mZenModeHelper.mConsolidatedPolicy.allowAlarms()).isTrue(); // default + assertThat(mZenModeHelper.mConsolidatedPolicy.allowMedia()).isTrue(); // default + assertThat(mZenModeHelper.mConsolidatedPolicy.allowSystem()).isTrue(); // custom + assertThat(mZenModeHelper.mConsolidatedPolicy.allowReminders()).isFalse(); // default + assertThat(mZenModeHelper.mConsolidatedPolicy.allowCalls()).isFalse(); // custom + assertThat(mZenModeHelper.mConsolidatedPolicy.allowMessages()).isTrue(); // default + assertThat(mZenModeHelper.mConsolidatedPolicy.allowRepeatCallers()).isFalse(); // custom + assertThat(mZenModeHelper.mConsolidatedPolicy.showBadges()).isFalse(); // custom + assertThat(mZenModeHelper.mConsolidatedPolicy.showFullScreenIntents()).isTrue(); // custom + } + + @Test + @DisableFlags(Flags.FLAG_MODES_API) + public void testUpdateConsolidatedPolicy_preModesApiDefaultAndCustomActive_mergesWithGlobal() { setupZenConfig(); // when there are two rules active, one inheriting the default policy and one setting its @@ -3309,6 +3738,68 @@ public class ZenModeHelperTest extends UiServiceTestCase { } @Test + @EnableFlags(Flags.FLAG_MODES_API) + public void testUpdateConsolidatedPolicy_modesApiDefaultAndCustomActive_mergesWithDefault() { + setupZenConfig(); + + // when there are two rules active, one inheriting the default policy and one setting its + // own custom policy, they should be merged to form the most restrictive combination. + + // rule 1: no custom policy + AutomaticZenRule zenRule = new AutomaticZenRule("name", + null, + new ComponentName(CUSTOM_PKG_NAME, "ScheduleConditionProvider"), + ZenModeConfig.toScheduleConditionId(new ScheduleInfo()), + null, + NotificationManager.INTERRUPTION_FILTER_PRIORITY, true); + String id = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), zenRule, + UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "test", Process.SYSTEM_UID); + + // enable rule 1 + mZenModeHelper.setAutomaticZenRuleState(id, + new Condition(zenRule.getConditionId(), "", STATE_TRUE), + UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, Process.SYSTEM_UID); + + // custom policy for rule 2 + ZenPolicy customPolicy = new ZenPolicy.Builder() + .allowAlarms(false) // more restrictive than default + .allowSystem(true) // more lenient than default + .allowRepeatCallers(false) // more restrictive than default + .allowCalls(ZenPolicy.PEOPLE_TYPE_NONE) // more restrictive than default + .showBadges(false) // more restrictive + .showPeeking(true) // more lenient + .build(); + + AutomaticZenRule zenRule2 = new AutomaticZenRule("name2", + null, + new ComponentName(CUSTOM_PKG_NAME, "ScheduleConditionProvider"), + ZenModeConfig.toScheduleConditionId(new ScheduleInfo()), + customPolicy, + NotificationManager.INTERRUPTION_FILTER_PRIORITY, true); + String id2 = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), zenRule2, + UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, "test", Process.SYSTEM_UID); + + // enable rule 2; this will update the consolidated policy + mZenModeHelper.setAutomaticZenRuleState(id2, + new Condition(zenRule2.getConditionId(), "", STATE_TRUE), + UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, Process.SYSTEM_UID); + + // now both rules should be on, and the consolidated policy should reflect the most + // restrictive option of each of the two + assertThat(mZenModeHelper.mConsolidatedPolicy.allowAlarms()).isFalse(); // custom stricter + assertThat(mZenModeHelper.mConsolidatedPolicy.allowMedia()).isTrue(); // default + assertThat(mZenModeHelper.mConsolidatedPolicy.allowSystem()).isFalse(); // default stricter + assertThat(mZenModeHelper.mConsolidatedPolicy.allowReminders()).isFalse(); // default + assertThat(mZenModeHelper.mConsolidatedPolicy.allowCalls()).isFalse(); // custom stricter + assertThat(mZenModeHelper.mConsolidatedPolicy.allowMessages()).isTrue(); // default + assertThat(mZenModeHelper.mConsolidatedPolicy.allowConversations()).isTrue(); // default + assertThat(mZenModeHelper.mConsolidatedPolicy.allowRepeatCallers()) + .isFalse(); // custom stricter + assertThat(mZenModeHelper.mConsolidatedPolicy.showBadges()).isFalse(); // custom stricter + assertThat(mZenModeHelper.mConsolidatedPolicy.showPeeking()).isFalse(); // default stricter + } + + @Test public void testUpdateConsolidatedPolicy_allowChannels() { mSetFlagsRule.enableFlags(Flags.FLAG_MODES_API); setupZenConfig(); @@ -3372,7 +3863,10 @@ public class ZenModeHelperTest extends UiServiceTestCase { null, new ComponentName(CUSTOM_PKG_NAME, "cls"), Uri.parse("priority"), - new ZenPolicy.Builder().allowMedia(true).build(), + new ZenPolicy.Builder() + .allowMedia(true) + .allowSystem(true) + .build(), NotificationManager.INTERRUPTION_FILTER_PRIORITY, true); String rule1Id = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), zenRuleWithPriority, UPDATE_ORIGIN_APP, "test", CUSTOM_PKG_UID); @@ -3394,10 +3888,10 @@ public class ZenModeHelperTest extends UiServiceTestCase { UPDATE_ORIGIN_APP, CUSTOM_PKG_UID); // Consolidated Policy should be default + rule1. - assertThat(mZenModeHelper.mConsolidatedPolicy.allowAlarms()).isFalse(); // default + assertThat(mZenModeHelper.mConsolidatedPolicy.allowAlarms()).isTrue(); // default assertThat(mZenModeHelper.mConsolidatedPolicy.allowMedia()).isTrue(); // priority rule - assertThat(mZenModeHelper.mConsolidatedPolicy.allowSystem()).isFalse(); // default - assertThat(mZenModeHelper.mConsolidatedPolicy.allowReminders()).isTrue(); // default + assertThat(mZenModeHelper.mConsolidatedPolicy.allowSystem()).isTrue(); // priority rule + assertThat(mZenModeHelper.mConsolidatedPolicy.allowReminders()).isFalse(); // default assertThat(mZenModeHelper.mConsolidatedPolicy.allowCalls()).isTrue(); // default assertThat(mZenModeHelper.mConsolidatedPolicy.allowMessages()).isTrue(); // default assertThat(mZenModeHelper.mConsolidatedPolicy.allowConversations()).isTrue(); // default @@ -3408,7 +3902,7 @@ public class ZenModeHelperTest extends UiServiceTestCase { public void zenRuleToAutomaticZenRule_allFields() { mSetFlagsRule.enableFlags(Flags.FLAG_MODES_API); when(mPackageManager.getPackagesForUid(anyInt())).thenReturn( - new String[] {OWNER.getPackageName()}); + new String[]{OWNER.getPackageName()}); ZenModeConfig.ZenRule rule = new ZenModeConfig.ZenRule(); rule.configurationActivity = CONFIG_ACTIVITY; @@ -3452,7 +3946,7 @@ public class ZenModeHelperTest extends UiServiceTestCase { public void automaticZenRuleToZenRule_allFields() { mSetFlagsRule.enableFlags(Flags.FLAG_MODES_API); when(mPackageManager.getPackagesForUid(anyInt())).thenReturn( - new String[] {OWNER.getPackageName()}); + new String[]{OWNER.getPackageName()}); AutomaticZenRule azr = new AutomaticZenRule.Builder(NAME, CONDITION_ID) .setEnabled(true) @@ -3478,7 +3972,8 @@ public class ZenModeHelperTest extends UiServiceTestCase { assertEquals(CONDITION_ID, storedRule.conditionId); assertEquals(INTERRUPTION_FILTER_ZR, storedRule.zenMode); assertEquals(ENABLED, storedRule.enabled); - assertEquals(POLICY, storedRule.zenPolicy); + assertEquals(mZenModeHelper.getDefaultZenPolicy().overwrittenWith(POLICY), + storedRule.zenPolicy); assertEquals(CONFIG_ACTIVITY, storedRule.configurationActivity); assertEquals(TYPE, storedRule.type); assertEquals(ALLOW_MANUAL, storedRule.allowManualInvocation); @@ -3561,12 +4056,12 @@ public class ZenModeHelperTest extends UiServiceTestCase { // Modifies the zen policy and device effects ZenPolicy policy = new ZenPolicy.Builder(rule.getZenPolicy()) - .allowPriorityChannels(true) + .allowPriorityChannels(false) .build(); ZenDeviceEffects deviceEffects = new ZenDeviceEffects.Builder(rule.getDeviceEffects()) - .setShouldDisplayGrayscale(true) - .build(); + .setShouldDisplayGrayscale(true) + .build(); AutomaticZenRule azrUpdate = new AutomaticZenRule.Builder(rule) .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY) .setZenPolicy(policy) @@ -3580,7 +4075,8 @@ public class ZenModeHelperTest extends UiServiceTestCase { // UPDATE_ORIGIN_USER should change the bitmask and change the values. assertThat(rule.getInterruptionFilter()).isEqualTo(INTERRUPTION_FILTER_PRIORITY); - assertThat(rule.getZenPolicy().getPriorityChannels()).isEqualTo(ZenPolicy.STATE_ALLOW); + assertThat(rule.getZenPolicy().getPriorityChannels()).isEqualTo(ZenPolicy.STATE_DISALLOW); + assertThat(rule.getDeviceEffects().shouldDisplayGrayscale()).isTrue(); ZenRule storedRule = mZenModeHelper.mConfig.automaticRules.get(ruleId); @@ -3770,9 +4266,9 @@ public class ZenModeHelperTest extends UiServiceTestCase { @Test @EnableFlags(Flags.FLAG_MODES_API) public void updateAutomaticZenRule_nullPolicyUpdate() { - // Adds a starting rule with empty zen policies and device effects + // Adds a starting rule with set zen policy and empty device effects AutomaticZenRule azrBase = new AutomaticZenRule.Builder(NAME, CONDITION_ID) - .setZenPolicy(new ZenPolicy.Builder().build()) + .setZenPolicy(POLICY) .build(); // Adds the rule using the app, to avoid having any user modified bits set. String ruleId = mZenModeHelper.addAutomaticZenRule(mContext.getPackageName(), @@ -3790,8 +4286,10 @@ public class ZenModeHelperTest extends UiServiceTestCase { Process.SYSTEM_UID); rule = mZenModeHelper.getAutomaticZenRule(ruleId); - // When AZR's ZenPolicy is null, we expect the updated rule's policy to be null. - assertThat(rule.getZenPolicy()).isNull(); + // When AZR's ZenPolicy is null, we expect the updated rule's policy to be unchanged + // (equivalent to the provided policy, with additional fields filled in with defaults). + assertThat(rule.getZenPolicy()).isEqualTo( + mZenModeHelper.getDefaultZenPolicy().overwrittenWith(POLICY)); } @Test @@ -3847,13 +4345,13 @@ public class ZenModeHelperTest extends UiServiceTestCase { assertThat(storedRule.canBeUpdatedByApp()).isFalse(); assertThat(storedRule.zenPolicyUserModifiedFields).isEqualTo( ZenPolicy.FIELD_ALLOW_CHANNELS - | ZenPolicy.FIELD_PRIORITY_CATEGORY_REMINDERS - | ZenPolicy.FIELD_PRIORITY_CATEGORY_EVENTS - | ZenPolicy.FIELD_PRIORITY_CATEGORY_SYSTEM - | ZenPolicy.FIELD_VISUAL_EFFECT_FULL_SCREEN_INTENT - | ZenPolicy.FIELD_VISUAL_EFFECT_LIGHTS - | ZenPolicy.FIELD_VISUAL_EFFECT_PEEK - | ZenPolicy.FIELD_VISUAL_EFFECT_AMBIENT + | ZenPolicy.FIELD_PRIORITY_CATEGORY_REMINDERS + | ZenPolicy.FIELD_PRIORITY_CATEGORY_EVENTS + | ZenPolicy.FIELD_PRIORITY_CATEGORY_SYSTEM + | ZenPolicy.FIELD_VISUAL_EFFECT_FULL_SCREEN_INTENT + | ZenPolicy.FIELD_VISUAL_EFFECT_LIGHTS + | ZenPolicy.FIELD_VISUAL_EFFECT_PEEK + | ZenPolicy.FIELD_VISUAL_EFFECT_AMBIENT ); } @@ -4016,6 +4514,7 @@ public class ZenModeHelperTest extends UiServiceTestCase { final int[] actualStatus = new int[2]; ZenModeHelper.Callback callback = new ZenModeHelper.Callback() { int i = 0; + @Override void onAutomaticRuleStatusChanged(int userId, String pkg, String id, int status) { if (Objects.equals(createdId, id)) { @@ -4056,6 +4555,7 @@ public class ZenModeHelperTest extends UiServiceTestCase { final int[] actualStatus = new int[2]; ZenModeHelper.Callback callback = new ZenModeHelper.Callback() { int i = 0; + @Override void onAutomaticRuleStatusChanged(int userId, String pkg, String id, int status) { if (Objects.equals(createdId, id)) { @@ -4202,6 +4702,7 @@ public class ZenModeHelperTest extends UiServiceTestCase { .build()), eq(UPDATE_ORIGIN_APP)); } + @Test public void testDeviceEffects_noChangeToConsolidatedEffects_notApplied() { mSetFlagsRule.enableFlags(android.app.Flags.FLAG_MODES_API); @@ -4607,7 +5108,8 @@ public class ZenModeHelperTest extends UiServiceTestCase { .comparingElementsUsing(IGNORE_METADATA) .containsExactly( expectedImplicitRule(CUSTOM_PKG_NAME, ZEN_MODE_IMPORTANT_INTERRUPTIONS, - null, true)); + mZenModeHelper.mConfig.toZenPolicy(), // copy of global config + true)); } @Test @@ -4626,7 +5128,9 @@ public class ZenModeHelperTest extends UiServiceTestCase { assertThat(mZenModeHelper.mConfig.automaticRules.values()) .comparingElementsUsing(IGNORE_METADATA) .containsExactly( - expectedImplicitRule(CUSTOM_PKG_NAME, ZEN_MODE_ALARMS, null, true)); + expectedImplicitRule(CUSTOM_PKG_NAME, ZEN_MODE_ALARMS, + mZenModeHelper.mConfig.toZenPolicy(), // copy of global config + true)); } @Test @@ -4820,6 +5324,10 @@ public class ZenModeHelperTest extends UiServiceTestCase { mZenModeHelper.applyGlobalPolicyAsImplicitZenRule(pkg, CUSTOM_PKG_UID, originalPolicy); String ruleId = getOnlyElement(mZenModeHelper.mConfig.automaticRules.keySet()); + // Store this for checking later. + ZenPolicy originalEffectiveZenPolicy = new ZenPolicy.Builder( + mZenModeHelper.mConfig.toZenPolicy()).allowMedia(true).build(); + // From user, update that rule's policy. AutomaticZenRule rule = mZenModeHelper.getAutomaticZenRule(ruleId); ZenPolicy userUpdateZenPolicy = new ZenPolicy.Builder().disallowAllSounds() @@ -4839,7 +5347,9 @@ public class ZenModeHelperTest extends UiServiceTestCase { .comparingElementsUsing(IGNORE_METADATA) .containsExactly( expectedImplicitRule(pkg, ZEN_MODE_IMPORTANT_INTERRUPTIONS, - userUpdateZenPolicy, + // the final policy for the rule should contain the user's update + // overlaid on top of the original existing policy. + originalEffectiveZenPolicy.overwrittenWith(userUpdateZenPolicy), /* conditionActive= */ null)); } @@ -4854,6 +5364,10 @@ public class ZenModeHelperTest extends UiServiceTestCase { mZenModeHelper.applyGlobalPolicyAsImplicitZenRule(pkg, CUSTOM_PKG_UID, originalPolicy); String ruleId = getOnlyElement(mZenModeHelper.mConfig.automaticRules.keySet()); + // Store this for checking later. + ZenPolicy originalEffectiveZenPolicy = new ZenPolicy.Builder( + mZenModeHelper.mConfig.toZenPolicy()).allowMedia(true).build(); + // From user, update something in that rule, but not the ZenPolicy. AutomaticZenRule rule = mZenModeHelper.getAutomaticZenRule(ruleId); AutomaticZenRule userUpdateRule = new AutomaticZenRule.Builder(rule) @@ -4873,7 +5387,7 @@ public class ZenModeHelperTest extends UiServiceTestCase { .allowPriorityChannels(true) .build(); assertThat(getOnlyElement(mZenModeHelper.mConfig.automaticRules.values()).zenPolicy) - .isEqualTo(appsSecondZenPolicy); + .isEqualTo(originalEffectiveZenPolicy.overwrittenWith(appsSecondZenPolicy)); } @Test @@ -4905,13 +5419,17 @@ public class ZenModeHelperTest extends UiServiceTestCase { } @Test - public void getNotificationPolicyFromImplicitZenRule_ruleWithoutPolicy_returnsGlobalPolicy() { + public void getNotificationPolicyFromImplicitZenRule_ruleWithoutPolicy_copiesGlobalPolicy() { mSetFlagsRule.enableFlags(android.app.Flags.FLAG_MODES_API); + mZenModeHelper.mConfig.allowCalls = true; + mZenModeHelper.mConfig.allowConversations = false; + // Implicit rule will get the global policy at the time of rule creation. mZenModeHelper.applyGlobalZenModeAsImplicitZenRule(CUSTOM_PKG_NAME, CUSTOM_PKG_UID, ZEN_MODE_ALARMS); - mZenModeHelper.mConfig.allowCalls = true; - mZenModeHelper.mConfig.allowConversations = false; + + // If the policy then changes afterwards, we should keep the snapshotted version. + mZenModeHelper.mConfig.allowCalls = false; Policy readPolicy = mZenModeHelper.getNotificationPolicyFromImplicitZenRule( CUSTOM_PKG_NAME); @@ -4952,7 +5470,7 @@ public class ZenModeHelperTest extends UiServiceTestCase { p.recycle(); } }, - "Ignoring timestamp and userModifiedFields"); + "Ignoring timestamp and userModifiedFields"); private ZenRule expectedImplicitRule(String ownerPkg, int zenMode, ZenPolicy policy, @Nullable Boolean conditionActive) { @@ -4962,7 +5480,7 @@ public class ZenModeHelperTest extends UiServiceTestCase { if (conditionActive != null) { rule.condition = conditionActive ? new Condition(rule.conditionId, - mContext.getString(R.string.zen_mode_implicit_activated), STATE_TRUE) + mContext.getString(R.string.zen_mode_implicit_activated), STATE_TRUE) : new Condition(rule.conditionId, mContext.getString(R.string.zen_mode_implicit_deactivated), STATE_FALSE); @@ -5030,8 +5548,35 @@ public class ZenModeHelperTest extends UiServiceTestCase { assertEquals(STATE_ALLOW, dndProto.getNotificationList().getNumber()); } + private void checkDndProtoMatchesDefaultZenConfig(DNDPolicyProto dndProto) { + if (!Flags.modesApi()) { + checkDndProtoMatchesSetupZenConfig(dndProto); + return; + } + + // When modes_api flag is on, the default zen config is the device defaults. + assertThat(dndProto.getAlarms().getNumber()).isEqualTo(STATE_ALLOW); + assertThat(dndProto.getMedia().getNumber()).isEqualTo(STATE_ALLOW); + assertThat(dndProto.getSystem().getNumber()).isEqualTo(STATE_DISALLOW); + assertThat(dndProto.getReminders().getNumber()).isEqualTo(STATE_DISALLOW); + assertThat(dndProto.getCalls().getNumber()).isEqualTo(STATE_ALLOW); + assertThat(dndProto.getAllowCallsFrom().getNumber()).isEqualTo(PEOPLE_STARRED); + assertThat(dndProto.getMessages().getNumber()).isEqualTo(STATE_ALLOW); + assertThat(dndProto.getAllowMessagesFrom().getNumber()).isEqualTo(PEOPLE_STARRED); + assertThat(dndProto.getEvents().getNumber()).isEqualTo(STATE_DISALLOW); + assertThat(dndProto.getRepeatCallers().getNumber()).isEqualTo(STATE_ALLOW); + assertThat(dndProto.getFullscreen().getNumber()).isEqualTo(STATE_DISALLOW); + assertThat(dndProto.getLights().getNumber()).isEqualTo(STATE_DISALLOW); + assertThat(dndProto.getPeek().getNumber()).isEqualTo(STATE_DISALLOW); + assertThat(dndProto.getStatusBar().getNumber()).isEqualTo(STATE_ALLOW); + assertThat(dndProto.getBadge().getNumber()).isEqualTo(STATE_ALLOW); + assertThat(dndProto.getAmbient().getNumber()).isEqualTo(STATE_DISALLOW); + assertThat(dndProto.getNotificationList().getNumber()).isEqualTo(STATE_ALLOW); + } + private static void withoutWtfCrash(Runnable test) { - Log.TerribleFailureHandler oldHandler = Log.setWtfHandler((tag, what, system) -> {}); + Log.TerribleFailureHandler oldHandler = Log.setWtfHandler((tag, what, system) -> { + }); try { test.run(); } finally { diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenPolicyTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenPolicyTest.java index 4ed55df7775c..57e11328d5e1 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/ZenPolicyTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenPolicyTest.java @@ -269,6 +269,78 @@ public class ZenPolicyTest extends UiServiceTestCase { } @Test + public void testZenPolicyOverwrite_allUnsetPolicies() { + mSetFlagsRule.enableFlags(Flags.FLAG_MODES_API); + + ZenPolicy.Builder builder = new ZenPolicy.Builder(); + ZenPolicy unset = builder.build(); + + builder.allowCalls(ZenPolicy.PEOPLE_TYPE_CONTACTS); + builder.allowMedia(false); + builder.allowEvents(true); + builder.showFullScreenIntent(false); + builder.showInNotificationList(false); + ZenPolicy set = builder.build(); + + ZenPolicy overwritten = set.overwrittenWith(unset); + assertThat(overwritten).isEqualTo(set); + + // should actually work the other way too. + ZenPolicy overwrittenWithSet = unset.overwrittenWith(set); + assertThat(overwrittenWithSet).isEqualTo(set); + } + + @Test + public void testZenPolicyOverwrite_someOverlappingFields_takeNewPolicy() { + mSetFlagsRule.enableFlags(Flags.FLAG_MODES_API); + + ZenPolicy p1 = new ZenPolicy.Builder() + .allowCalls(ZenPolicy.PEOPLE_TYPE_CONTACTS) + .allowMessages(ZenPolicy.PEOPLE_TYPE_STARRED) + .allowMedia(false) + .showBadges(true) + .build(); + + ZenPolicy p2 = new ZenPolicy.Builder() + .allowRepeatCallers(false) + .allowConversations(ZenPolicy.CONVERSATION_SENDERS_IMPORTANT) + .allowMessages(ZenPolicy.PEOPLE_TYPE_NONE) + .showBadges(false) + .showPeeking(true) + .build(); + + // when p1 is overwritten with p2, all values from p2 win regardless of strictness, and + // remaining fields take values from p1. + ZenPolicy p1OverwrittenWithP2 = p1.overwrittenWith(p2); + assertThat(p1OverwrittenWithP2.getPriorityCallSenders()) + .isEqualTo(ZenPolicy.PEOPLE_TYPE_CONTACTS); // from p1 + assertThat(p1OverwrittenWithP2.getPriorityMessageSenders()) + .isEqualTo(ZenPolicy.PEOPLE_TYPE_NONE); // from p2 + assertThat(p1OverwrittenWithP2.getPriorityCategoryRepeatCallers()) + .isEqualTo(ZenPolicy.STATE_DISALLOW); // from p2 + assertThat(p1OverwrittenWithP2.getPriorityCategoryMedia()) + .isEqualTo(ZenPolicy.STATE_DISALLOW); // from p1 + assertThat(p1OverwrittenWithP2.getVisualEffectBadge()) + .isEqualTo(ZenPolicy.STATE_DISALLOW); // from p2 + assertThat(p1OverwrittenWithP2.getVisualEffectPeek()) + .isEqualTo(ZenPolicy.STATE_ALLOW); // from p2 + + ZenPolicy p2OverwrittenWithP1 = p2.overwrittenWith(p1); + assertThat(p2OverwrittenWithP1.getPriorityCallSenders()) + .isEqualTo(ZenPolicy.PEOPLE_TYPE_CONTACTS); // from p1 + assertThat(p2OverwrittenWithP1.getPriorityMessageSenders()) + .isEqualTo(ZenPolicy.PEOPLE_TYPE_STARRED); // from p1 + assertThat(p2OverwrittenWithP1.getPriorityCategoryRepeatCallers()) + .isEqualTo(ZenPolicy.STATE_DISALLOW); // from p2 + assertThat(p2OverwrittenWithP1.getPriorityCategoryMedia()) + .isEqualTo(ZenPolicy.STATE_DISALLOW); // from p1 + assertThat(p2OverwrittenWithP1.getVisualEffectBadge()) + .isEqualTo(ZenPolicy.STATE_ALLOW); // from p1 + assertThat(p2OverwrittenWithP1.getVisualEffectPeek()) + .isEqualTo(ZenPolicy.STATE_ALLOW); // from p2 + } + + @Test public void testZenPolicyMessagesInvalid() { ZenPolicy.Builder builder = new ZenPolicy.Builder(); 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 ba7b52e368f3..2a89b02482b3 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java @@ -1762,32 +1762,6 @@ public class ActivityRecordTests extends WindowTestsBase { assertEquals(1, task.getChildCount()); } - /** - * Test that an activity will not be destroyed if it is marked as non-destroyable. - */ - @Test - public void testSafelyDestroy_nonDestroyable() { - final ActivityRecord activity = createActivityWithTask(); - doReturn(false).when(activity).isDestroyable(); - - activity.safelyDestroy("test"); - - verify(activity, never()).destroyImmediately(anyString()); - } - - /** - * Test that an activity will not be destroyed if it is marked as non-destroyable. - */ - @Test - public void testSafelyDestroy_destroyable() { - final ActivityRecord activity = createActivityWithTask(); - doReturn(true).when(activity).isDestroyable(); - - activity.safelyDestroy("test"); - - verify(activity).destroyImmediately(anyString()); - } - @Test public void testRemoveImmediately() { final Consumer<Consumer<ActivityRecord>> test = setup -> { 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 c82f7513e347..29faed195b4e 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java @@ -132,8 +132,10 @@ import org.junit.runner.RunWith; import org.mockito.MockitoSession; import org.mockito.quality.Strictness; +import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; +import java.util.List; import java.util.Set; /** @@ -425,6 +427,12 @@ public class ActivityStarterTests extends WindowTestsBase { doNothing().when(mMockPackageManager).notifyPackageUse(anyString(), anyInt()); doReturn(mock(PackageArchiver.class)).when(mMockPackageManager).getPackageArchiver(); + final AndroidPackage mockPackage = mock(AndroidPackage.class); + final SigningDetails signingDetails = mock(SigningDetails.class); + doReturn(mockPackage).when(mMockPackageManager).getPackage(anyInt()); + doReturn(signingDetails).when(mockPackage).getSigningDetails(); + doReturn(false).when(signingDetails).hasAncestorOrSelfWithDigest(any()); + final Intent intent = new Intent(); intent.addFlags(launchFlags); intent.setComponent(ActivityBuilder.getDefaultComponent()); @@ -557,6 +565,86 @@ public class ActivityStarterTests extends WindowTestsBase { return Pair.create(splitPrimaryActivity, splitSecondActivity); } + /** + * This test ensures that if the intent is being delivered to a desktop mode unfocused task + * while it is already on top, reports it as delivering to top. + */ + @Test + public void testDesktopModeDeliverToTop() { + final ActivityStarter starter = prepareStarter( + FLAG_ACTIVITY_RESET_TASK_IF_NEEDED | FLAG_ACTIVITY_SINGLE_TOP, + false /* mockGetRootTask */); + final List<ActivityRecord> activities = createActivitiesInDesktopMode(); + + // Set focus back to the first task. + activities.get(0).moveFocusableActivityToTop("testDesktopModeDeliverToTop"); + + // Start activity and delivered new intent. + starter.getIntent().setComponent(activities.get(3).mActivityComponent); + doReturn(activities.get(3)).when(mRootWindowContainer).findTask(any(), any()); + final int result = starter.setReason("testDesktopModeDeliverToTop").execute(); + + // Ensure result is delivering intent to top. + assertEquals(START_DELIVERED_TO_TOP, result); + } + + /** + * This test ensures that if the intent is being delivered to a desktop mode unfocused task + * reports it is brought to front instead of delivering to top. + */ + @Test + public void testDesktopModeTaskToFront() { + final ActivityStarter starter = prepareStarter( + FLAG_ACTIVITY_RESET_TASK_IF_NEEDED | FLAG_ACTIVITY_SINGLE_TOP, false); + final List<ActivityRecord> activities = createActivitiesInDesktopMode(); + final ActivityRecord desktopModeFocusActivity = activities.get(0); + final ActivityRecord desktopModeReusableActivity = activities.get(1); + final ActivityRecord desktopModeTopActivity = new ActivityBuilder(mAtm).setCreateTask(true) + .setParentTask(desktopModeReusableActivity.getRootTask()).build(); + assertTrue(desktopModeTopActivity.inMultiWindowMode()); + + // Let first stack has focus. + desktopModeFocusActivity.moveFocusableActivityToTop("testDesktopModeTaskToFront"); + + // Start activity and delivered new intent. + starter.getIntent().setComponent(desktopModeReusableActivity.mActivityComponent); + doReturn(desktopModeReusableActivity).when(mRootWindowContainer).findTask(any(), any()); + final int result = starter.setReason("testDesktopModeMoveToFront").execute(); + + // Ensure result is moving task to front. + assertEquals(START_TASK_TO_FRONT, result); + } + + /** Returns 4 activities. */ + private List<ActivityRecord> createActivitiesInDesktopMode() { + final TestDesktopOrganizer desktopOrganizer = new TestDesktopOrganizer(mAtm); + List<ActivityRecord> activityRecords = new ArrayList<>(); + + for (int i = 0; i < 4; i++) { + Rect bounds = new Rect(desktopOrganizer.getDefaultDesktopTaskBounds()); + bounds.offset(20 * i, 20 * i); + desktopOrganizer.createTask(bounds); + } + + for (int i = 0; i < 4; i++) { + activityRecords.add(new TaskBuilder(mSupervisor) + .setParentTask(desktopOrganizer.mTasks.get(i)) + .setCreateActivity(true) + .build() + .getTopMostActivity()); + } + + for (int i = 0; i < 4; i++) { + activityRecords.get(i).setVisibleRequested(true); + } + + for (int i = 0; i < 4; i++) { + assertEquals(desktopOrganizer.mTasks.get(i), activityRecords.get(i).getRootTask()); + } + + return activityRecords; + } + @Test public void testMoveVisibleTaskToFront() { final ActivityRecord activity = new TaskBuilder(mSupervisor) 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 402cbccbca01..c44be7b9db51 100644 --- a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java @@ -56,6 +56,7 @@ import android.os.Bundle; import android.os.RemoteCallback; import android.os.RemoteException; import android.platform.test.annotations.Presubmit; +import android.platform.test.annotations.RequiresFlagsEnabled; import android.util.ArraySet; import android.view.WindowManager; import android.window.BackAnimationAdapter; @@ -69,6 +70,7 @@ import android.window.TaskSnapshot; import android.window.WindowOnBackInvokedDispatcher; import com.android.server.LocalServices; +import com.android.window.flags.Flags; import org.junit.Before; import org.junit.Test; @@ -81,6 +83,12 @@ import java.util.ArrayList; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; +/** + * Tests for the {@link BackNavigationController} class. + * + * Build/Install/Run: + * atest WmTests:BackNavigationControllerTests + */ @Presubmit @RunWith(WindowTestRunner.class) public class BackNavigationControllerTests extends WindowTestsBase { @@ -623,6 +631,22 @@ public class BackNavigationControllerTests extends WindowTestsBase { 0, navigationObserver.getCount()); } + @Test + @RequiresFlagsEnabled(Flags.FLAG_EMBEDDED_ACTIVITY_BACK_NAV_FLAG) + public void testAdjacentFocusInActivityEmbedding() { + Task task = createTask(mDefaultDisplay); + TaskFragment primary = createTaskFragmentWithActivity(task); + TaskFragment secondary = createTaskFragmentWithActivity(task); + primary.setAdjacentTaskFragment(secondary); + secondary.setAdjacentTaskFragment(primary); + + WindowState windowState = mock(WindowState.class); + doReturn(windowState).when(mWm).getFocusedWindowLocked(); + doReturn(primary).when(windowState).getTaskFragment(); + + startBackNavigation(); + verify(mWm).moveFocusToAdjacentWindow(any(), anyInt()); + } /** * Test with diff --git a/services/tests/wmtests/src/com/android/server/wm/CompatModePackagesTests.java b/services/tests/wmtests/src/com/android/server/wm/CompatModePackagesTests.java index c18726350d81..91375940226a 100644 --- a/services/tests/wmtests/src/com/android/server/wm/CompatModePackagesTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/CompatModePackagesTests.java @@ -18,6 +18,7 @@ package com.android.server.wm; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock; +import static com.android.server.wm.CompatScaleProvider.COMPAT_SCALE_MODE_GAME; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -27,6 +28,8 @@ import static org.mockito.ArgumentMatchers.anyString; import android.app.GameManagerInternal; import android.content.pm.ApplicationInfo; +import android.content.res.CompatibilityInfo.CompatScale; +import android.os.UserHandle; import android.platform.test.annotations.Presubmit; import androidx.test.filters.SmallTest; @@ -55,6 +58,17 @@ public class CompatModePackagesTests extends SystemServiceTestsBase { public void setUp() { mAtm = mSystemServicesTestRule.getActivityTaskManagerService(); mGm = mock(GameManagerInternal.class); + mAtm.registerCompatScaleProvider(COMPAT_SCALE_MODE_GAME, new CompatScaleProvider() { + @Override + public CompatScale getCompatScale(String packageName, int uid) { + int userId = UserHandle.getUserHandleForUid(uid).getIdentifier(); + float scalingFactor = mGm.getResolutionScalingFactor(packageName, userId); + if (scalingFactor > 0) { + return new CompatScale(1f / scalingFactor); + } + return null; + } + }); } @After @@ -67,7 +81,7 @@ public class CompatModePackagesTests extends SystemServiceTestsBase { LocalServices.addService(GameManagerInternal.class, mGm); float scale = 0.25f; doReturn(scale).when(mGm).getResolutionScalingFactor(anyString(), anyInt()); - assertEquals(mAtm.mCompatModePackages.getCompatScale(TEST_PACKAGE, TEST_USER_ID), 1 / scale, + assertEquals(1 / scale, mAtm.mCompatModePackages.getCompatScale(TEST_PACKAGE, TEST_USER_ID), 0.01f); } diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java index 782d89cdcd29..95850ac2f3b2 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java @@ -2131,8 +2131,8 @@ public class DisplayContentTests extends WindowTestsBase { // Once transition starts, rotation is applied and transition shows DC rotating. testPlayer.startTransition(); waitUntilHandlersIdle(); - verify(activity1).ensureActivityConfiguration(anyBoolean(), anyBoolean()); - verify(activity2).ensureActivityConfiguration(anyBoolean(), anyBoolean()); + verify(activity1).ensureActivityConfiguration(anyBoolean()); + verify(activity2).ensureActivityConfiguration(anyBoolean()); assertNotEquals(origRot, dc.getConfiguration().windowConfiguration.getRotation()); assertNotNull(testPlayer.mLastReady); assertTrue(testPlayer.mController.isPlaying()); diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java index be96e60917a3..9e00f927a568 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java @@ -283,12 +283,12 @@ public class DisplayPolicyTests extends WindowTestsBase { policy.screenTurnedOff(); policy.setAwake(false); - policy.screenTurnedOn(null /* screenOnListener */); + policy.screenTurningOn(null /* screenOnListener */); assertTrue(wpc.isShowingUiWhileDozing()); policy.screenTurnedOff(); assertFalse(wpc.isShowingUiWhileDozing()); - policy.screenTurnedOn(null /* screenOnListener */); + policy.screenTurningOn(null /* screenOnListener */); assertTrue(wpc.isShowingUiWhileDozing()); policy.setAwake(true); assertFalse(wpc.isShowingUiWhileDozing()); diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java index 5518c604446d..6759eef2066d 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java @@ -197,10 +197,10 @@ public class SizeCompatTests extends WindowTestsBase { mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */); // Translucent Activity final ActivityRecord translucentActivity = new ActivityBuilder(mAtm) + .setActivityTheme(android.R.style.Theme_Translucent) .setLaunchedFromUid(mActivity.getUid()) .setScreenOrientation(SCREEN_ORIENTATION_PORTRAIT) .build(); - doReturn(false).when(translucentActivity).fillsParent(); mTask.addChild(translucentActivity); translucentActivity.setState(DESTROYED, "testing"); @@ -225,10 +225,10 @@ public class SizeCompatTests extends WindowTestsBase { // Translucent Activity final ActivityRecord translucentActivity = new ActivityBuilder(mAtm) + .setActivityTheme(android.R.style.Theme_Translucent) .setLaunchedFromUid(mActivity.getUid()) .setScreenOrientation(SCREEN_ORIENTATION_PORTRAIT) .build(); - doReturn(false).when(translucentActivity).fillsParent(); mTask.addChild(translucentActivity); spyOn(translucentActivity.mLetterboxUiController); @@ -300,10 +300,10 @@ public class SizeCompatTests extends WindowTestsBase { // Translucent Activity final ActivityRecord translucentActivity = new ActivityBuilder(mAtm) + .setActivityTheme(android.R.style.Theme_Translucent) .setLaunchedFromUid(mActivity.getUid()) .setScreenOrientation(SCREEN_ORIENTATION_LANDSCAPE) .build(); - doReturn(false).when(translucentActivity).fillsParent(); mTask.addChild(translucentActivity); spyOn(translucentActivity.mLetterboxUiController); @@ -376,10 +376,10 @@ public class SizeCompatTests extends WindowTestsBase { // Launch translucent Activity final ActivityRecord translucentActivity = new ActivityBuilder(mAtm) + .setActivityTheme(android.R.style.Theme_Translucent) .setLaunchedFromUid(mActivity.getUid()) .setScreenOrientation(SCREEN_ORIENTATION_PORTRAIT) .build(); - doReturn(false).when(translucentActivity).fillsParent(); mTask.addChild(translucentActivity); // Transparent strategy applied assertTrue(translucentActivity.mLetterboxUiController.hasInheritedLetterboxBehavior()); @@ -404,10 +404,10 @@ public class SizeCompatTests extends WindowTestsBase { // Launch translucent Activity final ActivityRecord translucentActivity = new ActivityBuilder(mAtm) + .setActivityTheme(android.R.style.Theme_Translucent) .setLaunchedFromUid(mActivity.getUid()) .setScreenOrientation(SCREEN_ORIENTATION_PORTRAIT) .build(); - doReturn(false).when(translucentActivity).fillsParent(); mTask.addChild(translucentActivity); // Transparent strategy applied assertTrue(translucentActivity.mLetterboxUiController.hasInheritedLetterboxBehavior()); @@ -441,10 +441,10 @@ public class SizeCompatTests extends WindowTestsBase { // Launch translucent Activity final ActivityRecord translucentActivity = new ActivityBuilder(mAtm) + .setActivityTheme(android.R.style.Theme_Translucent) .setLaunchedFromUid(mActivity.getUid()) .setScreenOrientation(SCREEN_ORIENTATION_PORTRAIT) .build(); - doReturn(false).when(translucentActivity).fillsParent(); mTask.addChild(translucentActivity); // Transparent strategy applied assertTrue(translucentActivity.mLetterboxUiController.hasInheritedLetterboxBehavior()); @@ -465,12 +465,12 @@ public class SizeCompatTests extends WindowTestsBase { mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */); // Translucent Activity final ActivityRecord translucentActivity = new ActivityBuilder(mAtm) + .setActivityTheme(android.R.style.Theme_Translucent) .setLaunchedFromUid(mActivity.getUid()) .setScreenOrientation(SCREEN_ORIENTATION_LANDSCAPE) .setMinAspectRatio(1.1f) .setMaxAspectRatio(3f) .build(); - doReturn(false).when(translucentActivity).fillsParent(); mTask.addChild(translucentActivity); // We check bounds final Rect opaqueBounds = mActivity.getConfiguration().windowConfiguration.getBounds(); @@ -493,9 +493,9 @@ public class SizeCompatTests extends WindowTestsBase { mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */); // Translucent Activity final ActivityRecord translucentActivity = new ActivityBuilder(mAtm) + .setActivityTheme(android.R.style.Theme_Translucent) .setLaunchedFromUid(mActivity.getUid()) .build(); - doReturn(false).when(translucentActivity).fillsParent(); final Configuration requestedConfig = translucentActivity.getRequestedOverrideConfiguration(); final WindowConfiguration translucentWinConf = requestedConfig.windowConfiguration; @@ -525,12 +525,12 @@ public class SizeCompatTests extends WindowTestsBase { mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */); // Translucent Activity final ActivityRecord translucentActivity = new ActivityBuilder(mAtm) + .setActivityTheme(android.R.style.Theme_Translucent) .setLaunchedFromUid(mActivity.getUid()) .setScreenOrientation(SCREEN_ORIENTATION_LANDSCAPE) .setMinAspectRatio(1.1f) .setMaxAspectRatio(3f) .build(); - doReturn(false).when(translucentActivity).fillsParent(); mTask.addChild(translucentActivity); // We check bounds final Rect opaqueBounds = mActivity.getConfiguration().windowConfiguration.getBounds(); @@ -538,10 +538,10 @@ public class SizeCompatTests extends WindowTestsBase { assertEquals(opaqueBounds, translucentRequestedBounds); // Launch another translucent activity final ActivityRecord translucentActivity2 = new ActivityBuilder(mAtm) + .setActivityTheme(android.R.style.Theme_Translucent) .setLaunchedFromUid(mActivity.getUid()) .setScreenOrientation(SCREEN_ORIENTATION_LANDSCAPE) .build(); - doReturn(false).when(translucentActivity2).fillsParent(); mTask.addChild(translucentActivity2); // We check bounds final Rect translucent2RequestedBounds = translucentActivity2.getRequestedOverrideBounds(); @@ -558,9 +558,9 @@ public class SizeCompatTests extends WindowTestsBase { // simplicity. doReturn(true).when(mActivity).isEmbedded(); // Translucent Activity - final ActivityRecord translucentActivity = new ActivityBuilder(mAtm).build(); + final ActivityRecord translucentActivity = new ActivityBuilder(mAtm) + .setActivityTheme(android.R.style.Theme_Translucent).build(); doReturn(false).when(translucentActivity).matchParentBounds(); - doReturn(false).when(translucentActivity).fillsParent(); mTask.addChild(translucentActivity); // Check the strategy has not being applied assertFalse(translucentActivity.mLetterboxUiController.hasInheritedLetterboxBehavior()); @@ -580,10 +580,10 @@ public class SizeCompatTests extends WindowTestsBase { assertFalse(mActivity.inSizeCompatMode()); // We launch a transparent activity final ActivityRecord translucentActivity = new ActivityBuilder(mAtm) + .setActivityTheme(android.R.style.Theme_Translucent) .setLaunchedFromUid(mActivity.getUid()) .setScreenOrientation(SCREEN_ORIENTATION_PORTRAIT) .build(); - doReturn(false).when(translucentActivity).fillsParent(); mTask.addChild(translucentActivity); // It should not be in SCM assertFalse(translucentActivity.inSizeCompatMode()); @@ -600,12 +600,16 @@ public class SizeCompatTests extends WindowTestsBase { mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */); // Translucent Activity final ActivityRecord translucentActivity = new ActivityBuilder(mAtm) + .setActivityTheme(android.R.style.Theme_Translucent) .setLaunchedFromUid(mActivity.getUid()) .build(); - doReturn(false).when(translucentActivity).fillsParent(); - spyOn(mActivity); + assertFalse(translucentActivity.fillsParent()); + assertTrue(mActivity.fillsParent()); + mActivity.finishing = true; + assertFalse(mActivity.occludesParent()); mTask.addChild(translucentActivity); - verify(mActivity).isFinishing(); + // The translucent activity won't inherit letterbox behavior from a finishing activity. + assertFalse(translucentActivity.mLetterboxUiController.hasInheritedLetterboxBehavior()); } @Test @@ -619,10 +623,10 @@ public class SizeCompatTests extends WindowTestsBase { prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT); // We launch a transparent activity final ActivityRecord translucentActivity = new ActivityBuilder(mAtm) + .setActivityTheme(android.R.style.Theme_Translucent) .setLaunchedFromUid(mActivity.getUid()) .setScreenOrientation(SCREEN_ORIENTATION_PORTRAIT) .build(); - doReturn(false).when(translucentActivity).fillsParent(); mTask.addChild(translucentActivity); assertEquals(translucentActivity.getBounds(), mActivity.getBounds()); @@ -655,10 +659,10 @@ public class SizeCompatTests extends WindowTestsBase { // We launch a transparent activity final ActivityRecord translucentActivity = new ActivityBuilder(mAtm) + .setActivityTheme(android.R.style.Theme_Translucent) .setLaunchedFromUid(mActivity.getUid()) .setScreenOrientation(SCREEN_ORIENTATION_PORTRAIT) .build(); - doReturn(false).when(translucentActivity).fillsParent(); mTask.addChild(translucentActivity); // The transparent activity inherits the compat display insets of the opaque activity @@ -1020,8 +1024,17 @@ public class SizeCompatTests extends WindowTestsBase { // Activity is sandboxed due to fixed aspect ratio. assertActivityMaxBoundsSandboxed(); + // Prepare the states for verifying relaunching after changing orientation. + mActivity.finishRelaunching(); + mActivity.setState(RESUMED, "testFixedAspectRatioOrientationChangeOrientation"); + mActivity.setLastReportedConfiguration(mAtm.getGlobalConfiguration(), + mActivity.getConfiguration()); + // Change the fixed orientation. mActivity.setRequestedOrientation(SCREEN_ORIENTATION_LANDSCAPE); + assertTrue(mActivity.isRelaunching()); + assertTrue(mActivity.mLetterboxUiController + .getIsRelaunchingAfterRequestedOrientationChanged()); assertFitted(); assertEquals(originalBounds.width(), mActivity.getBounds().height()); 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 22ddf8420121..7c7e562426c2 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java @@ -32,6 +32,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.never; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.when; import static com.android.server.wm.ActivityRecord.State.RESUMED; import static com.android.server.wm.TaskFragment.EMBEDDED_DIM_AREA_PARENT_TASK; import static com.android.server.wm.TaskFragment.EMBEDDED_DIM_AREA_TASK_FRAGMENT; @@ -46,7 +47,9 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.clearInvocations; +import static org.mockito.Mockito.mock; +import android.content.pm.SigningDetails; import android.content.res.Configuration; import android.graphics.Color; import android.graphics.Rect; @@ -61,17 +64,22 @@ import android.window.TaskFragmentOrganizer; import androidx.test.filters.MediumTest; +import com.android.server.pm.pkg.AndroidPackage; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import java.util.Collections; +import java.util.Set; + /** * Test class for {@link TaskFragment}. * * Build/Install/Run: - * atest WmTests:TaskFragmentTest + * atest WmTests:TaskFragmentTest */ @MediumTest @Presubmit @@ -537,6 +545,49 @@ public class TaskFragmentTest extends WindowTestsBase { } @Test + public void testIsAllowedToEmbedActivityInTrustedModeByHostPackage() { + final TaskFragment taskFragment = new TaskFragmentBuilder(mAtm) + .setCreateParentTask() + .createActivityCount(1) + .build(); + final ActivityRecord activity = taskFragment.getTopMostActivity(); + + final String mockCert = "MOCKCERT"; + final AndroidPackage hostPackage = mock(AndroidPackage.class); + final SigningDetails signingDetails = mock(SigningDetails.class); + when(signingDetails.hasAncestorOrSelfWithDigest(any())) + .thenAnswer(invocation -> ((Set) invocation.getArgument(0)).contains(mockCert)); + doReturn(signingDetails).when(hostPackage).getSigningDetails(); + + // Should return false when no certs are specified + assertFalse(taskFragment.isAllowedToEmbedActivityInTrustedModeByHostPackage( + activity, hostPackage)); + + // Should return true when the cert is specified in <activity> + activity.info.setKnownActivityEmbeddingCerts(Set.of(mockCert)); + assertTrue(taskFragment.isAllowedToEmbedActivityInTrustedModeByHostPackage( + activity, hostPackage)); + + // Should return false when the certs specified in <activity> doesn't match + activity.info.setKnownActivityEmbeddingCerts(Set.of("WRONGCERT")); + assertFalse(taskFragment.isAllowedToEmbedActivityInTrustedModeByHostPackage( + activity, hostPackage)); + + // Should return true when the certs is specified in <application> + activity.info.setKnownActivityEmbeddingCerts(Collections.emptySet()); + activity.info.applicationInfo.setKnownActivityEmbeddingCerts(Set.of(mockCert)); + assertTrue(taskFragment.isAllowedToEmbedActivityInTrustedModeByHostPackage( + activity, hostPackage)); + + // When the certs is specified in both <activity> and <application>, <activity> takes + // precedence + activity.info.setKnownActivityEmbeddingCerts(Set.of("WRONGCERT")); + activity.info.applicationInfo.setKnownActivityEmbeddingCerts(Set.of(mockCert)); + assertFalse(taskFragment.isAllowedToEmbedActivityInTrustedModeByHostPackage( + activity, hostPackage)); + } + + @Test public void testIgnoreRequestedOrientationForActivityEmbeddingSplit() { // Setup two activities in ActivityEmbedding split. final Task task = createTask(mDisplayContent); diff --git a/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java b/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java index 45ecc3f762ec..00ecd008cde7 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java +++ b/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java @@ -215,7 +215,7 @@ class TestDisplayContent extends DisplayContent { doReturn(false).when(newDisplay).supportsSystemDecorations(); } // Update the display policy to make the screen fully turned on so animation is allowed - displayPolicy.screenTurnedOn(null /* screenOnListener */); + displayPolicy.screenTurningOn(null /* screenOnListener */); displayPolicy.finishKeyguardDrawn(); displayPolicy.finishWindowsDrawn(); displayPolicy.finishScreenTurningOn(); diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java index 114b9c3a68f2..a0bafb64090f 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java @@ -20,6 +20,7 @@ import static android.app.AppOpsManager.OP_NONE; import static android.app.WindowConfiguration.ACTIVITY_TYPE_DREAM; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.app.WindowConfiguration.ROTATION_UNDEFINED; +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_UNDEFINED; @@ -133,7 +134,9 @@ import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; /** Common base class for window manager unit test classes. */ class WindowTestsBase extends SystemServiceTestsBase { @@ -226,7 +229,7 @@ class WindowTestsBase extends SystemServiceTestsBase { mDefaultDisplay = mWm.mRoot.getDefaultDisplay(); // Update the display policy to make the screen fully turned on so animation is allowed final DisplayPolicy displayPolicy = mDefaultDisplay.getDisplayPolicy(); - displayPolicy.screenTurnedOn(null /* screenOnListener */); + displayPolicy.screenTurningOn(null /* screenOnListener */); displayPolicy.finishKeyguardDrawn(); displayPolicy.finishWindowsDrawn(); displayPolicy.finishScreenTurningOn(); @@ -1892,6 +1895,55 @@ class WindowTestsBase extends SystemServiceTestsBase { } } + static class TestDesktopOrganizer extends WindowOrganizerTests.StubOrganizer { + final int mDesktopModeDefaultWidthDp = 840; + final int mDesktopModeDefaultHeightDp = 630; + final int mDesktopDensity = 284; + + final ActivityTaskManagerService mService; + final TaskDisplayArea mDefaultTDA; + List<Task> mTasks; + final DisplayContent mDisplay; + Rect mStableBounds; + + TestDesktopOrganizer(ActivityTaskManagerService service, DisplayContent display) { + mService = service; + mDefaultTDA = display.getDefaultTaskDisplayArea(); + mDisplay = display; + mService.mTaskOrganizerController.registerTaskOrganizer(this); + mTasks = new ArrayList<>(); + mStableBounds = display.getBounds(); + } + + TestDesktopOrganizer(ActivityTaskManagerService service) { + this(service, service.mTaskSupervisor.mRootWindowContainer.getDefaultDisplay()); + } + + public Task createTask(Rect bounds) { + Task task = mService.mTaskOrganizerController.createRootTask( + mDisplay, WINDOWING_MODE_FREEFORM, null); + task.setBounds(bounds); + mTasks.add(task); + spyOn(task); + return task; + } + + public Rect getDefaultDesktopTaskBounds() { + int width = (int) (mDesktopModeDefaultWidthDp * mDesktopDensity + 0.5f); + int height = (int) (mDesktopModeDefaultHeightDp * mDesktopDensity + 0.5f); + Rect outBounds = new Rect(); + + outBounds.set(0, 0, width, height); + // Center the task in stable bounds + outBounds.offset( + mStableBounds.centerX() - outBounds.centerX(), + mStableBounds.centerY() - outBounds.centerY() + ); + return outBounds; + } + + } + static TestWindowToken createTestWindowToken(int type, DisplayContent dc) { return createTestWindowToken(type, dc, false /* persistOnEmpty */); } diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java index 9fc64feb4b25..a58cf5fcd620 100644 --- a/services/usage/java/com/android/server/usage/UsageStatsService.java +++ b/services/usage/java/com/android/server/usage/UsageStatsService.java @@ -1526,14 +1526,15 @@ public class UsageStatsService extends SystemService implements * Called by the Binder stub. */ UsageEvents queryEvents(int userId, long beginTime, long endTime, int flags) { - return queryEventsWithTypes(userId, beginTime, endTime, flags, EmptyArray.INT); + return queryEventsWithQueryFilters(userId, beginTime, endTime, flags, + /* eventTypeFilter= */ EmptyArray.INT, /* pkgNameFilter= */ null); } /** * Called by the Binder stub. */ - UsageEvents queryEventsWithTypes(int userId, long beginTime, long endTime, int flags, - int[] eventTypeFilter) { + UsageEvents queryEventsWithQueryFilters(int userId, long beginTime, long endTime, int flags, + int[] eventTypeFilter, ArraySet<String> pkgNameFilter) { synchronized (mLock) { if (!mUserUnlockedStates.contains(userId)) { Slog.w(TAG, "Failed to query events for locked user " + userId); @@ -1544,7 +1545,7 @@ public class UsageStatsService extends SystemService implements if (service == null) { return null; // user was stopped or removed } - return service.queryEvents(beginTime, endTime, flags, eventTypeFilter); + return service.queryEvents(beginTime, endTime, flags, eventTypeFilter, pkgNameFilter); } } @@ -2276,7 +2277,7 @@ public class UsageStatsService extends SystemService implements } private UsageEvents queryEventsHelper(int userId, long beginTime, long endTime, - String callingPackage, int[] eventTypeFilter) { + String callingPackage, int[] eventTypeFilter, ArraySet<String> pkgNameFilter) { final int callingUid = Binder.getCallingUid(); final int callingPid = Binder.getCallingPid(); final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller( @@ -2295,8 +2296,8 @@ public class UsageStatsService extends SystemService implements if (hideLocusIdEvents) flags |= UsageEvents.HIDE_LOCUS_EVENTS; if (obfuscateNotificationEvents) flags |= UsageEvents.OBFUSCATE_NOTIFICATION_EVENTS; - return UsageStatsService.this.queryEventsWithTypes(userId, beginTime, endTime, - flags, eventTypeFilter); + return UsageStatsService.this.queryEventsWithQueryFilters(userId, + beginTime, endTime, flags, eventTypeFilter, pkgNameFilter); } finally { Binder.restoreCallingIdentity(token); } @@ -2414,7 +2415,8 @@ public class UsageStatsService extends SystemService implements } return queryEventsHelper(UserHandle.getCallingUserId(), beginTime, endTime, - callingPackage, /* eventTypeFilter= */ EmptyArray.INT); + callingPackage, /* eventTypeFilter= */ EmptyArray.INT, + /* pkgNameFilter= */ null); } @Override @@ -2440,7 +2442,8 @@ public class UsageStatsService extends SystemService implements } return queryEventsHelper(userId, query.getBeginTimeMillis(), - query.getEndTimeMillis(), callingPackage, query.getEventTypes()); + query.getEndTimeMillis(), callingPackage, query.getEventTypes(), + /* pkgNameFilter= */ new ArraySet<>(query.getPackageNames())); } @Override @@ -2476,7 +2479,8 @@ public class UsageStatsService extends SystemService implements } return queryEventsHelper(userId, beginTime, endTime, callingPackage, - /* eventTypeFilter= */ EmptyArray.INT); + /* eventTypeFilter= */ EmptyArray.INT, + /* pkgNameFilter= */ null); } @Override diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java index 3bc77526a967..96f45fa952bf 100644 --- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java +++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java @@ -536,13 +536,14 @@ class UserUsageStatsService { } UsageEvents queryEvents(final long beginTime, final long endTime, int flags, - int[] eventTypeFilter) { + int[] eventTypeFilter, ArraySet<String> pkgNameFilter) { if (!validRange(checkAndGetTimeLocked(), beginTime, endTime)) { return null; } // Ensure valid event type filter. final boolean isQueryForAllEvents = ArrayUtils.isEmpty(eventTypeFilter); + final boolean isQueryForAllPackages = pkgNameFilter == null || pkgNameFilter.isEmpty(); final boolean[] queryEventFilter = new boolean[Event.MAX_EVENT_TYPE + 1]; if (!isQueryForAllEvents) { for (int eventType : eventTypeFilter) { @@ -589,6 +590,11 @@ class UserUsageStatsService { if ((flags & OBFUSCATE_INSTANT_APPS) == OBFUSCATE_INSTANT_APPS) { event = event.getObfuscatedIfInstantApp(); } + + if (!isQueryForAllPackages && !pkgNameFilter.contains(event.mPackage)) { + continue; + } + if (event.mPackage != null) { names.add(event.mPackage); } diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java index 94c737d61b0a..a089f5c9d641 100644 --- a/telecomm/java/android/telecom/PhoneAccount.java +++ b/telecomm/java/android/telecom/PhoneAccount.java @@ -18,6 +18,7 @@ package android.telecom; import static android.Manifest.permission.MODIFY_PHONE_STATE; +import android.annotation.FlaggedApi; import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.annotation.SystemApi; @@ -30,11 +31,15 @@ import android.os.Parcelable; import android.telephony.CarrierConfigManager; import android.telephony.TelephonyManager; import android.text.TextUtils; +import android.util.ArraySet; + +import com.android.internal.telephony.flags.Flags; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Objects; +import java.util.Set; /** * Represents a distinct method to place or receive a phone call. Apps which can place calls and @@ -491,6 +496,7 @@ public final class PhoneAccount implements Parcelable { private final Bundle mExtras; private boolean mIsEnabled; private String mGroupId; + private final Set<PhoneAccountHandle> mSimultaneousCallingRestriction; @Override public boolean equals(Object o) { @@ -508,7 +514,9 @@ public final class PhoneAccount implements Parcelable { Objects.equals(mShortDescription, that.mShortDescription) && Objects.equals(mSupportedUriSchemes, that.mSupportedUriSchemes) && areBundlesEqual(mExtras, that.mExtras) && - Objects.equals(mGroupId, that.mGroupId); + Objects.equals(mGroupId, that.mGroupId) + && Objects.equals(mSimultaneousCallingRestriction, + that.mSimultaneousCallingRestriction); } @Override @@ -516,7 +524,7 @@ public final class PhoneAccount implements Parcelable { return Objects.hash(mAccountHandle, mAddress, mSubscriptionAddress, mCapabilities, mHighlightColor, mLabel, mShortDescription, mSupportedUriSchemes, mSupportedAudioRoutes, - mExtras, mIsEnabled, mGroupId); + mExtras, mIsEnabled, mGroupId, mSimultaneousCallingRestriction); } /** @@ -537,6 +545,7 @@ public final class PhoneAccount implements Parcelable { private Bundle mExtras; private boolean mIsEnabled = false; private String mGroupId = ""; + private Set<PhoneAccountHandle> mSimultaneousCallingRestriction = null; /** * Creates a builder with the specified {@link PhoneAccountHandle} and label. @@ -787,6 +796,57 @@ public final class PhoneAccount implements Parcelable { } /** + * Restricts the ability of this {@link PhoneAccount} to ONLY support simultaneous calling + * with the other {@link PhoneAccountHandle}s in this Set. + * <p> + * If two or more {@link PhoneAccount}s support calling simultaneously, it means that + * Telecom allows the user to place additional outgoing calls and receive additional + * incoming calls using other {@link PhoneAccount}s while this PhoneAccount also has one or + * more active calls. + * <p> + * If this setter method is never called or cleared using + * {@link #clearSimultaneousCallingRestriction()}, there is no restriction and all + * {@link PhoneAccount}s registered to Telecom by this package support simultaneous calling. + * <p> + * Note: Simultaneous calling restrictions can only be placed on {@link PhoneAccount}s that + * were registered by the same application. Simultaneous calling across applications is + * always possible as long as the {@link Connection} supports hold. If a + * {@link PhoneAccountHandle} is included here and the package name doesn't match this + * application's package name, {@link TelecomManager#registerPhoneAccount(PhoneAccount)} + * will throw a {@link SecurityException}. + * + * @param handles The other {@link PhoneAccountHandle}s that support calling simultaneously + * with this one. Use {@link #clearSimultaneousCallingRestriction()} to remove the + * restriction and allow simultaneous calling to be supported across all + * {@link PhoneAccount}s registered by this package. + * @return The Builder used to set up the new PhoneAccount. + */ + @FlaggedApi(Flags.FLAG_SIMULTANEOUS_CALLING_INDICATIONS) + public @NonNull Builder setSimultaneousCallingRestriction( + @NonNull Set<PhoneAccountHandle> handles) { + if (handles == null) { + throw new IllegalArgumentException("the Set of PhoneAccountHandles must not be " + + "null"); + } + mSimultaneousCallingRestriction = handles; + return this; + } + + /** + * Clears a previously set simultaneous calling restriction set when + * {@link PhoneAccount.Builder#Builder(PhoneAccount)} is used to create a new PhoneAccount + * from an existing one. + * + * @return The Builder used to set up the new PhoneAccount. + * @see #setSimultaneousCallingRestriction(Set) + */ + @FlaggedApi(Flags.FLAG_SIMULTANEOUS_CALLING_INDICATIONS) + public @NonNull Builder clearSimultaneousCallingRestriction() { + mSimultaneousCallingRestriction = null; + return this; + } + + /** * Creates an instance of a {@link PhoneAccount} based on the current builder settings. * * @return The {@link PhoneAccount}. @@ -810,7 +870,8 @@ public final class PhoneAccount implements Parcelable { mExtras, mSupportedAudioRoutes, mIsEnabled, - mGroupId); + mGroupId, + mSimultaneousCallingRestriction); } } @@ -827,7 +888,8 @@ public final class PhoneAccount implements Parcelable { Bundle extras, int supportedAudioRoutes, boolean isEnabled, - String groupId) { + String groupId, + Set<PhoneAccountHandle> simultaneousCallingRestriction) { mAccountHandle = account; mAddress = address; mSubscriptionAddress = subscriptionAddress; @@ -841,6 +903,7 @@ public final class PhoneAccount implements Parcelable { mSupportedAudioRoutes = supportedAudioRoutes; mIsEnabled = isEnabled; mGroupId = groupId; + mSimultaneousCallingRestriction = simultaneousCallingRestriction; } public static Builder builder( @@ -1050,6 +1113,49 @@ public final class PhoneAccount implements Parcelable { return (mCapabilities & CAPABILITY_SELF_MANAGED) == CAPABILITY_SELF_MANAGED; } + /** + * If a restriction is set (see {@link #hasSimultaneousCallingRestriction()}), this method + * returns the Set of {@link PhoneAccountHandle}s that are allowed to support calls + * simultaneously with this {@link PhoneAccount}. + * <p> + * If this {@link PhoneAccount} is busy with one or more ongoing calls, a restriction is set on + * this PhoneAccount (see {@link #hasSimultaneousCallingRestriction()} to check), and a new + * incoming or outgoing call is received or placed on a PhoneAccount that is not in this Set, + * Telecom will reject or cancel the pending call in favor of keeping the ongoing call alive. + * <p> + * Note: Simultaneous calling restrictions can only be placed on {@link PhoneAccount}s that + * were registered by the same application. Simultaneous calling across applications is + * always possible as long as the {@link Connection} supports hold. + * + * @return the Set of {@link PhoneAccountHandle}s that this {@link PhoneAccount} supports + * simultaneous calls with. + * @throws IllegalStateException If there is no restriction set on this {@link PhoneAccount} + * and this method is called. Whether or not there is a restriction can be checked using + * {@link #hasSimultaneousCallingRestriction()}. + */ + @FlaggedApi(Flags.FLAG_SIMULTANEOUS_CALLING_INDICATIONS) + public @NonNull Set<PhoneAccountHandle> getSimultaneousCallingRestriction() { + if (mSimultaneousCallingRestriction == null) { + throw new IllegalStateException("This method can not be called if there is no " + + "simultaneous calling restriction. See #hasSimultaneousCallingRestriction"); + } + return mSimultaneousCallingRestriction; + } + + /** + * Whether or not this {@link PhoneAccount} contains a simultaneous calling restriction on it. + * + * @return {@code true} if this PhoneAccount contains a simultaneous calling restriction, + * {@code false} if it does not. Use {@link #getSimultaneousCallingRestriction()} to query which + * other {@link PhoneAccount}s support simultaneous calling with this one. + * @see #getSimultaneousCallingRestriction() for more information on how the sinultaneous + * calling restriction works. + */ + @FlaggedApi(Flags.FLAG_SIMULTANEOUS_CALLING_INDICATIONS) + public boolean hasSimultaneousCallingRestriction() { + return mSimultaneousCallingRestriction != null; + } + // // Parcelable implementation // @@ -1095,6 +1201,12 @@ public final class PhoneAccount implements Parcelable { out.writeBundle(mExtras); out.writeString(mGroupId); out.writeInt(mSupportedAudioRoutes); + if (mSimultaneousCallingRestriction == null) { + out.writeBoolean(false); + } else { + out.writeBoolean(true); + out.writeTypedList(mSimultaneousCallingRestriction.stream().toList()); + } } public static final @android.annotation.NonNull Creator<PhoneAccount> CREATOR @@ -1140,6 +1252,13 @@ public final class PhoneAccount implements Parcelable { mExtras = in.readBundle(); mGroupId = in.readString(); mSupportedAudioRoutes = in.readInt(); + if (in.readBoolean()) { + List<PhoneAccountHandle> list = new ArrayList<>(); + in.readTypedList(list, PhoneAccountHandle.CREATOR); + mSimultaneousCallingRestriction = new ArraySet<>(list); + } else { + mSimultaneousCallingRestriction = null; + } } @Override diff --git a/telecomm/java/android/telecom/Response.java b/telecomm/java/android/telecom/Response.java deleted file mode 100644 index ce7a7612786b..000000000000 --- a/telecomm/java/android/telecom/Response.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.telecom; - -/** - * @hide - */ -public interface Response<IN, OUT> { - - /** - * Provide a set of results. - * - * @param request The original request. - * @param result The results. - */ - void onResult(IN request, OUT... result); - - /** - * Indicates the inability to provide results. - * - * @param request The original request. - * @param code An integer code indicating the reason for failure. - * @param msg A message explaining the reason for failure. - */ - void onError(IN request, int code, String msg); -} diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java index a5c6d57aed82..1bf11df7059a 100644 --- a/telephony/java/android/telephony/SubscriptionManager.java +++ b/telephony/java/android/telephony/SubscriptionManager.java @@ -1618,14 +1618,15 @@ public class SubscriptionManager { } /** - * Register for changes to the list of active {@link SubscriptionInfo} records or to the - * individual records themselves. When a change occurs the onSubscriptionsChanged method of - * the listener will be invoked immediately if there has been a notification. The - * onSubscriptionChanged method will also be triggered once initially when calling this - * function. + * Register for changes to the list of {@link SubscriptionInfo} records or to the + * individual records (active or inactive) themselves. When a change occurs, the + * {@link OnSubscriptionsChangedListener#onSubscriptionsChanged()} method of + * the listener will be invoked immediately. The + * {@link OnSubscriptionsChangedListener#onSubscriptionsChanged()} method will also be invoked + * once initially when calling this method. * * @param listener an instance of {@link OnSubscriptionsChangedListener} with - * onSubscriptionsChanged overridden. + * {@link OnSubscriptionsChangedListener#onSubscriptionsChanged()} overridden. * @param executor the executor that will execute callbacks. */ public void addOnSubscriptionsChangedListener( @@ -1953,7 +1954,6 @@ public class SubscriptionManager { * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}. */ @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) - // @RequiresPermission(TODO(b/308809058)) public List<SubscriptionInfo> getActiveSubscriptionInfoList() { List<SubscriptionInfo> activeList = null; @@ -2010,6 +2010,9 @@ public class SubscriptionManager { * Create a new subscription manager instance that can see all subscriptions across * user profiles. * + * The permission check for accessing all subscriptions will be enforced upon calling the + * individual APIs linked below. + * * @return a SubscriptionManager that can see all subscriptions regardless its user profile * association. * @@ -2018,9 +2021,7 @@ public class SubscriptionManager { * @see UserHandle */ @FlaggedApi(Flags.FLAG_ENFORCE_SUBSCRIPTION_USER_FILTER) - // @RequiresPermission(TODO(b/308809058)) - // The permission check for accessing all subscriptions will be enforced upon calling the - // individual APIs linked above. + @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_PROFILES) @NonNull public SubscriptionManager createForAllUserProfiles() { return new SubscriptionManager(mContext, true/*isForAllUserProfiles*/); } @@ -2215,7 +2216,6 @@ public class SubscriptionManager { * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}. */ @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) - // @RequiresPermission(TODO(b/308809058)) public int getActiveSubscriptionInfoCount() { int result = 0; diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 9ec5f7a77b2c..cbd552454642 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -6888,6 +6888,7 @@ public class TelephonyManager { } } + // TODO(b/316183370): replace all @code with @link in javadoc after feature is released /** * @return true if the current device is "voice capable". * <p> @@ -6901,7 +6902,10 @@ public class TelephonyManager { * PackageManager.FEATURE_TELEPHONY system feature, which is available * on any device with a telephony radio, even if the device is * data-only. - * @deprecated Replaced by {@link #isDeviceVoiceCapable()} + * @deprecated Replaced by {@code #isDeviceVoiceCapable()}. Starting from Android 15, voice + * capability may also be overridden by carriers for a given subscription. For voice capable + * device (when {@code #isDeviceVoiceCapable} return {@code true}), caller should check for + * subscription-level voice capability as well. See {@code #isDeviceVoiceCapable} for details. */ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING) @Deprecated @@ -6923,9 +6927,10 @@ public class TelephonyManager { * .FEATURE_TELEPHONY system feature, which is available on any device with a telephony * radio, even if the device is data-only. * <p> - * To check if a subscription is "voice capable", call method - * {@link SubscriptionInfo#getServiceCapabilities()} and compare the result with - * bitmask {@link SubscriptionManager#SERVICE_CAPABILITY_VOICE}. + * Starting from Android 15, voice capability may also be overridden by carrier for a given + * subscription on a voice capable device. To check if a subscription is "voice capable", + * call method {@code SubscriptionInfo#getServiceCapabilities()} and check if + * {@code SubscriptionManager#SERVICE_CAPABILITY_VOICE} is included. * * @see SubscriptionInfo#getServiceCapabilities() */ @@ -6943,7 +6948,10 @@ public class TelephonyManager { * <p> * Note: Voicemail waiting sms, cell broadcasting sms, and MMS are * disabled when device doesn't support sms. - * @deprecated Replaced by {@link #isDeviceSmsCapable()} + * @deprecated Replaced by {@code #isDeviceSmsCapable()}. Starting from Android 15, SMS + * capability may also be overridden by carriers for a given subscription. For SMS capable + * device (when {@code #isDeviceSmsCapable} return {@code true}), caller should check for + * subscription-level SMS capability as well. See {@code #isDeviceSmsCapable} for details. */ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_MESSAGING) public boolean isSmsCapable() { @@ -6961,9 +6969,10 @@ public class TelephonyManager { * Note: Voicemail waiting SMS, cell broadcasting SMS, and MMS are * disabled when device doesn't support SMS. * <p> - * To check if a subscription is "SMS capable", call method - * {@link SubscriptionInfo#getServiceCapabilities()} and compare result with - * bitmask {@link SubscriptionManager#SERVICE_CAPABILITY_SMS}. + * Starting from Android 15, SMS capability may also be overridden by carriers for a given + * subscription on an SMS capable device. To check if a subscription is "SMS capable", + * call method {@code SubscriptionInfo#getServiceCapabilities()} and check if + * {@code SubscriptionManager#SERVICE_CAPABILITY_SMS} is included. * * @see SubscriptionInfo#getServiceCapabilities() */ @@ -13139,7 +13148,7 @@ public class TelephonyManager { */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) public ServiceState getServiceStateForSubscriber(int subId) { - return getServiceStateForSubscriber(getSubId(), false, false); + return getServiceStateForSubscriber(subId, false, false); } /** @@ -18483,7 +18492,6 @@ public class TelephonyManager { /** * Get last known cell identity. - * Require appropriate permissions, otherwise throws SecurityException. * * If there is current registered network this value will be same as the registered cell * identity. If the device goes out of service the previous cell identity is cached and @@ -18495,7 +18503,7 @@ public class TelephonyManager { @SystemApi @FlaggedApi(com.android.server.telecom.flags.Flags.FLAG_TELECOM_RESOLVE_HIDDEN_DEPENDENCIES) @RequiresPermission(allOf = {Manifest.permission.ACCESS_FINE_LOCATION, - "com.android.phone.permission.ACCESS_LAST_KNOWN_CELL_ID"}) + Manifest.permission.ACCESS_LAST_KNOWN_CELL_ID}) public @Nullable CellIdentity getLastKnownCellIdentity() { try { ITelephony telephony = getITelephony(); diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index acbf354bb4de..24296f4d9031 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -3078,6 +3078,16 @@ interface ITelephony { in List<String> satelliteCountryCodes); /** + * This API can be used in only testing to override oem-enabled satellite provision status. + * + * @param reset {@code true} mean the overriding status should not be used, {@code false} + * otherwise. + * @param isProvisioned The overriding provision status. + * @return {@code true} if the provision status is set successfully, {@code false} otherwise. + */ + boolean setOemEnabledSatelliteProvisionStatus(in boolean reset, in boolean isProvisioned); + + /** * Test method to confirm the file contents are not altered. */ @JavaPassthrough(annotation="@android.annotation.RequiresPermission(" diff --git a/tests/BinaryTransparencyHostTest/test-app/src/android/transparency/test/app/BinaryTransparencyTest.java b/tests/BinaryTransparencyHostTest/test-app/src/android/transparency/test/app/BinaryTransparencyTest.java index 2bc056ee743f..cee27b6847ec 100644 --- a/tests/BinaryTransparencyHostTest/test-app/src/android/transparency/test/app/BinaryTransparencyTest.java +++ b/tests/BinaryTransparencyHostTest/test-app/src/android/transparency/test/app/BinaryTransparencyTest.java @@ -16,6 +16,8 @@ package android.transparency.test.app; +import static android.Manifest.permission.GET_BACKGROUND_INSTALLED_PACKAGES; + import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; @@ -27,6 +29,7 @@ import android.util.Log; import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.runner.AndroidJUnit4; +import com.android.compatibility.common.util.ShellIdentityUtils; import com.android.internal.os.IBinaryTransparencyService.AppInfo; import org.junit.Before; @@ -116,7 +119,12 @@ public class BinaryTransparencyTest { @Test public void testCollectAllSilentInstalledMbaInfo() { // Action - var appInfoList = mBt.collectAllSilentInstalledMbaInfo(new Bundle()); + var appInfoList = + ShellIdentityUtils.invokeMethodWithShellPermissions( + mBt, + (Bt) -> + mBt.collectAllSilentInstalledMbaInfo(new Bundle()), + GET_BACKGROUND_INSTALLED_PACKAGES); // Verify assertThat(appInfoList).isNotEmpty(); // because we just installed from the host side diff --git a/tests/Input/src/com/android/server/input/InputManagerServiceTests.kt b/tests/Input/src/com/android/server/input/InputManagerServiceTests.kt index 7b191f8388c5..256a4696b763 100644 --- a/tests/Input/src/com/android/server/input/InputManagerServiceTests.kt +++ b/tests/Input/src/com/android/server/input/InputManagerServiceTests.kt @@ -144,7 +144,6 @@ class InputManagerServiceTests { verify(native).setTouchpadTapToClickEnabled(anyBoolean()) verify(native).setTouchpadRightClickZoneEnabled(anyBoolean()) verify(native).setShowTouches(anyBoolean()) - verify(native).reloadPointerIcons() verify(native).setMotionClassifierEnabled(anyBoolean()) verify(native).setMaximumObscuringOpacityForTouch(anyFloat()) verify(native).setStylusPointerIconEnabled(anyBoolean()) @@ -293,14 +292,16 @@ class InputManagerServiceTests { setVirtualMousePointerDisplayIdAndVerify(10) localService.setPointerIconVisible(false, 10) + verify(native).setPointerIconVisibility(10, false) verify(native).setPointerIconType(eq(PointerIcon.TYPE_NULL)) localService.setMousePointerAccelerationEnabled(false, 10) - verify(native).setMousePointerAccelerationEnabled(eq(false)) + verify(native).setMousePointerAccelerationEnabled(10, false) service.onDisplayRemoved(10) + verify(native).setPointerIconVisibility(10, true) verify(native).displayRemoved(eq(10)) verify(native).setPointerIconType(eq(PointerIcon.TYPE_NOT_SPECIFIED)) - verify(native).setMousePointerAccelerationEnabled(true) + verify(native).setMousePointerAccelerationEnabled(10, true) verifyNoMoreInteractions(native) // This call should not block because the virtual mouse pointer override was never removed. @@ -316,25 +317,26 @@ class InputManagerServiceTests { localService.setPointerIconVisible(false, 10) verify(native).setPointerIconType(eq(PointerIcon.TYPE_NULL)) + verify(native).setPointerIconVisibility(10, false) localService.setMousePointerAccelerationEnabled(false, 10) - verify(native).setMousePointerAccelerationEnabled(eq(false)) + verify(native).setMousePointerAccelerationEnabled(10, false) localService.setPointerIconVisible(true, 10) verify(native).setPointerIconType(eq(PointerIcon.TYPE_NOT_SPECIFIED)) + verify(native).setPointerIconVisibility(10, true) localService.setMousePointerAccelerationEnabled(true, 10) - verify(native).setMousePointerAccelerationEnabled(eq(true)) + verify(native).setMousePointerAccelerationEnabled(10, true) - // Verify that setting properties on a different display is not propagated until the - // pointer is moved to that display. localService.setPointerIconVisible(false, 20) + verify(native).setPointerIconVisibility(20, false) localService.setMousePointerAccelerationEnabled(false, 20) + verify(native).setMousePointerAccelerationEnabled(20, false) verifyNoMoreInteractions(native) clearInvocations(native) setVirtualMousePointerDisplayIdAndVerify(20) verify(native).setPointerIconType(eq(PointerIcon.TYPE_NULL)) - verify(native).setMousePointerAccelerationEnabled(eq(false)) } @Test @@ -342,12 +344,13 @@ class InputManagerServiceTests { localService.setPointerIconVisible(false, 10) localService.setMousePointerAccelerationEnabled(false, 10) + verify(native).setPointerIconVisibility(10, false) + verify(native).setMousePointerAccelerationEnabled(10, false) verifyNoMoreInteractions(native) setVirtualMousePointerDisplayIdAndVerify(10) verify(native).setPointerIconType(eq(PointerIcon.TYPE_NULL)) - verify(native).setMousePointerAccelerationEnabled(eq(false)) } @Test diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java index cbdcb8869628..518183f9cd64 100644 --- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java +++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java @@ -30,6 +30,7 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.pm.PackageManager; import android.content.rollback.RollbackInfo; import android.content.rollback.RollbackManager; import android.os.UserManager; @@ -146,7 +147,8 @@ public class RollbackTest { assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1); // Upgrade from v1 to v2, with rollbacks enabled. - Install.single(TestApp.A2).setEnableRollback().commit(); + Install.single(TestApp.A2).setEnableRollback().setRollbackImpactLevel( + PackageManager.ROLLBACK_USER_IMPACT_HIGH).commit(); assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); // The app should now be available for rollback. @@ -154,6 +156,8 @@ public class RollbackTest { assertThat(available).isNotStaged(); assertThat(available).packagesContainsExactly( Rollback.from(TestApp.A2).to(TestApp.A1)); + assertThat(available.getRollbackImpactLevel()).isEqualTo( + PackageManager.ROLLBACK_USER_IMPACT_HIGH); // We should not have received any rollback requests yet. // TODO: Possibly flaky if, by chance, some other app on device @@ -264,6 +268,8 @@ public class RollbackTest { RollbackInfo rollbackB = waitForAvailableRollback(TestApp.B); assertThat(rollbackB).packagesContainsExactly( Rollback.from(TestApp.B2).to(TestApp.B1)); + assertThat(rollbackB.getRollbackImpactLevel()).isEqualTo( + PackageManager.ROLLBACK_USER_IMPACT_LOW); // Register rollback committed receiver RollbackBroadcastReceiver rollbackReceiver = new RollbackBroadcastReceiver(); diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp index 45dd02c9b7be..f3f183815d0b 100644 --- a/tools/aapt2/cmd/Link.cpp +++ b/tools/aapt2/cmd/Link.cpp @@ -56,6 +56,7 @@ #include "java/JavaClassGenerator.h" #include "java/ManifestClassGenerator.h" #include "java/ProguardRules.h" +#include "link/FeatureFlagsFilter.h" #include "link/Linkers.h" #include "link/ManifestFixer.h" #include "link/NoDefaultResourceRemover.h" @@ -1987,6 +1988,19 @@ class Linker { context_->SetNameManglerPolicy(NameManglerPolicy{context_->GetCompilationPackage()}); context_->SetSplitNameDependencies(app_info_.split_name_dependencies); + FeatureFlagsFilterOptions flags_filter_options; + if (context_->GetMinSdkVersion() > SDK_UPSIDE_DOWN_CAKE) { + // For API version > U, PackageManager will dynamically read the flag values and disable + // manifest elements accordingly when parsing the manifest. + // For API version <= U, we remove disabled elements from the manifest with the filter. + flags_filter_options.remove_disabled_elements = false; + flags_filter_options.flags_must_have_value = false; + } + FeatureFlagsFilter flags_filter(options_.feature_flag_values, flags_filter_options); + if (!flags_filter.Consume(context_, manifest_xml.get())) { + return 1; + } + // Override the package ID when it is "android". if (context_->GetCompilationPackage() == "android") { context_->SetPackageId(kAndroidPackageId); @@ -2531,7 +2545,7 @@ int LinkCommand::Action(const std::vector<std::string>& args) { } for (const std::string& arg : all_feature_flags_args) { - if (ParseFeatureFlagsParameter(arg, context.GetDiagnostics(), &options_.feature_flag_values)) { + if (!ParseFeatureFlagsParameter(arg, context.GetDiagnostics(), &options_.feature_flag_values)) { return 1; } } diff --git a/tools/aapt2/cmd/Link.h b/tools/aapt2/cmd/Link.h index 26713fd92264..dc18b1ccda60 100644 --- a/tools/aapt2/cmd/Link.h +++ b/tools/aapt2/cmd/Link.h @@ -330,7 +330,11 @@ class LinkCommand : public Command { "should only be used together with the --static-lib flag.", &options_.merge_only); AddOptionalSwitch("-v", "Enables verbose logging.", &verbose_); - AddOptionalFlagList("--feature-flags", "Placeholder, to be implemented.", &feature_flags_args_); + AddOptionalFlagList("--feature-flags", + "Specify the values of feature flags. The pairs in the argument\n" + "are separated by ',' and the name is separated from the value by '='.\n" + "Example: \"flag1=true,flag2=false,flag3=\" (flag3 has no given value).", + &feature_flags_args_); } int Action(const std::vector<std::string>& args) override; diff --git a/tools/aapt2/cmd/Link_test.cpp b/tools/aapt2/cmd/Link_test.cpp index 7096f5cc54e3..9323f3b95eac 100644 --- a/tools/aapt2/cmd/Link_test.cpp +++ b/tools/aapt2/cmd/Link_test.cpp @@ -16,11 +16,10 @@ #include "Link.h" -#include <android-base/file.h> - -#include "AppInfo.h" #include "Diagnostics.h" #include "LoadedApk.h" +#include "android-base/file.h" +#include "android-base/stringprintf.h" #include "test/Test.h" using testing::Eq; @@ -993,4 +992,213 @@ TEST_F(LinkTest, LocaleConfigWrongLocaleFormat) { ASSERT_FALSE(Link(link_args, &diag)); } +static void BuildSDKWithFeatureFlagAttr(const std::string& apk_path, const std::string& java_path, + CommandTestFixture* fixture, android::IDiagnostics* diag) { + const std::string android_values = + R"(<resources> + <staging-public-group type="attr" first-id="0x01fe0063"> + <public name="featureFlag" /> + </staging-public-group> + <attr name="featureFlag" format="string" /> + </resources>)"; + + SourceXML source_xml{.res_file_path = "/res/values/values.xml", .file_contents = android_values}; + BuildSDK({source_xml}, apk_path, java_path, fixture, diag); +} + +TEST_F(LinkTest, FeatureFlagDisabled_SdkAtMostUDC) { + StdErrDiagnostics diag; + const std::string android_apk = GetTestPath("android.apk"); + const std::string android_java = GetTestPath("android-java"); + BuildSDKWithFeatureFlagAttr(android_apk, android_java, this, &diag); + + const std::string manifest_contents = android::base::StringPrintf( + R"(<uses-sdk android:minSdkVersion="%d" />" + <permission android:name="FOO" android:featureFlag="flag" />)", + SDK_UPSIDE_DOWN_CAKE); + auto app_manifest = ManifestBuilder(this) + .SetPackageName("com.example.app") + .AddContents(manifest_contents) + .Build(); + + auto app_link_args = LinkCommandBuilder(this) + .SetManifestFile(app_manifest) + .AddParameter("-I", android_apk) + .AddParameter("--feature-flags", "flag=false"); + + const std::string app_apk = GetTestPath("app.apk"); + BuildApk({}, app_apk, std::move(app_link_args), this, &diag); + + // Permission element should be removed if flag is disabled + auto apk = LoadedApk::LoadApkFromPath(app_apk, &diag); + ASSERT_THAT(apk, NotNull()); + auto apk_manifest = apk->GetManifest(); + ASSERT_THAT(apk_manifest, NotNull()); + auto root = apk_manifest->root.get(); + ASSERT_THAT(root, NotNull()); + auto maybe_removed = root->FindChild({}, "permission"); + ASSERT_THAT(maybe_removed, IsNull()); +} + +TEST_F(LinkTest, FeatureFlagEnabled_SdkAtMostUDC) { + StdErrDiagnostics diag; + const std::string android_apk = GetTestPath("android.apk"); + const std::string android_java = GetTestPath("android-java"); + BuildSDKWithFeatureFlagAttr(android_apk, android_java, this, &diag); + + const std::string manifest_contents = android::base::StringPrintf( + R"(<uses-sdk android:minSdkVersion="%d" />" + <permission android:name="FOO" android:featureFlag="flag" />)", + SDK_UPSIDE_DOWN_CAKE); + auto app_manifest = ManifestBuilder(this) + .SetPackageName("com.example.app") + .AddContents(manifest_contents) + .Build(); + + auto app_link_args = LinkCommandBuilder(this) + .SetManifestFile(app_manifest) + .AddParameter("-I", android_apk) + .AddParameter("--feature-flags", "flag=true"); + + const std::string app_apk = GetTestPath("app.apk"); + BuildApk({}, app_apk, std::move(app_link_args), this, &diag); + + // Permission element should be kept if flag is enabled + auto apk = LoadedApk::LoadApkFromPath(app_apk, &diag); + ASSERT_THAT(apk, NotNull()); + auto apk_manifest = apk->GetManifest(); + ASSERT_THAT(apk_manifest, NotNull()); + auto root = apk_manifest->root.get(); + ASSERT_THAT(root, NotNull()); + auto maybe_removed = root->FindChild({}, "permission"); + ASSERT_THAT(maybe_removed, NotNull()); +} + +TEST_F(LinkTest, FeatureFlagWithNoValue_SdkAtMostUDC) { + StdErrDiagnostics diag; + const std::string android_apk = GetTestPath("android.apk"); + const std::string android_java = GetTestPath("android-java"); + BuildSDKWithFeatureFlagAttr(android_apk, android_java, this, &diag); + + const std::string manifest_contents = android::base::StringPrintf( + R"(<uses-sdk android:minSdkVersion="%d" />" + <permission android:name="FOO" android:featureFlag="flag" />)", + SDK_UPSIDE_DOWN_CAKE); + auto app_manifest = ManifestBuilder(this) + .SetPackageName("com.example.app") + .AddContents(manifest_contents) + .Build(); + + auto app_link_args = LinkCommandBuilder(this) + .SetManifestFile(app_manifest) + .AddParameter("-I", android_apk) + .AddParameter("--feature-flags", "flag="); + + // Flags must have values if <= UDC + const std::string app_apk = GetTestPath("app.apk"); + ASSERT_FALSE(Link(app_link_args.Build(app_apk), &diag)); +} + +TEST_F(LinkTest, FeatureFlagDisabled_SdkAfterUDC) { + StdErrDiagnostics diag; + const std::string android_apk = GetTestPath("android.apk"); + const std::string android_java = GetTestPath("android-java"); + BuildSDKWithFeatureFlagAttr(android_apk, android_java, this, &diag); + + const std::string manifest_contents = android::base::StringPrintf( + R"(<uses-sdk android:minSdkVersion="%d" />" + <permission android:name="FOO" android:featureFlag="flag" />)", + SDK_CUR_DEVELOPMENT); + auto app_manifest = ManifestBuilder(this) + .SetPackageName("com.example.app") + .AddContents(manifest_contents) + .Build(); + + auto app_link_args = LinkCommandBuilder(this) + .SetManifestFile(app_manifest) + .AddParameter("-I", android_apk) + .AddParameter("--feature-flags", "flag=false"); + + const std::string app_apk = GetTestPath("app.apk"); + BuildApk({}, app_apk, std::move(app_link_args), this, &diag); + + // Permission element should be kept if > UDC, regardless of flag value + auto apk = LoadedApk::LoadApkFromPath(app_apk, &diag); + ASSERT_THAT(apk, NotNull()); + auto apk_manifest = apk->GetManifest(); + ASSERT_THAT(apk_manifest, NotNull()); + auto root = apk_manifest->root.get(); + ASSERT_THAT(root, NotNull()); + auto maybe_removed = root->FindChild({}, "permission"); + ASSERT_THAT(maybe_removed, NotNull()); +} + +TEST_F(LinkTest, FeatureFlagEnabled_SdkAfterUDC) { + StdErrDiagnostics diag; + const std::string android_apk = GetTestPath("android.apk"); + const std::string android_java = GetTestPath("android-java"); + BuildSDKWithFeatureFlagAttr(android_apk, android_java, this, &diag); + + const std::string manifest_contents = android::base::StringPrintf( + R"(<uses-sdk android:minSdkVersion="%d" />" + <permission android:name="FOO" android:featureFlag="flag" />)", + SDK_CUR_DEVELOPMENT); + auto app_manifest = ManifestBuilder(this) + .SetPackageName("com.example.app") + .AddContents(manifest_contents) + .Build(); + + auto app_link_args = LinkCommandBuilder(this) + .SetManifestFile(app_manifest) + .AddParameter("-I", android_apk) + .AddParameter("--feature-flags", "flag=true"); + + const std::string app_apk = GetTestPath("app.apk"); + BuildApk({}, app_apk, std::move(app_link_args), this, &diag); + + // Permission element should be kept if > UDC, regardless of flag value + auto apk = LoadedApk::LoadApkFromPath(app_apk, &diag); + ASSERT_THAT(apk, NotNull()); + auto apk_manifest = apk->GetManifest(); + ASSERT_THAT(apk_manifest, NotNull()); + auto root = apk_manifest->root.get(); + ASSERT_THAT(root, NotNull()); + auto maybe_removed = root->FindChild({}, "permission"); + ASSERT_THAT(maybe_removed, NotNull()); +} + +TEST_F(LinkTest, FeatureFlagWithNoValue_SdkAfterUDC) { + StdErrDiagnostics diag; + const std::string android_apk = GetTestPath("android.apk"); + const std::string android_java = GetTestPath("android-java"); + BuildSDKWithFeatureFlagAttr(android_apk, android_java, this, &diag); + + const std::string manifest_contents = android::base::StringPrintf( + R"(<uses-sdk android:minSdkVersion="%d" />" + <permission android:name="FOO" android:featureFlag="flag" />)", + SDK_CUR_DEVELOPMENT); + auto app_manifest = ManifestBuilder(this) + .SetPackageName("com.example.app") + .AddContents(manifest_contents) + .Build(); + + auto app_link_args = LinkCommandBuilder(this) + .SetManifestFile(app_manifest) + .AddParameter("-I", android_apk) + .AddParameter("--feature-flags", "flag="); + + const std::string app_apk = GetTestPath("app.apk"); + BuildApk({}, app_apk, std::move(app_link_args), this, &diag); + + // Permission element should be kept if > UDC, regardless of flag value + auto apk = LoadedApk::LoadApkFromPath(app_apk, &diag); + ASSERT_THAT(apk, NotNull()); + auto apk_manifest = apk->GetManifest(); + ASSERT_THAT(apk_manifest, NotNull()); + auto root = apk_manifest->root.get(); + ASSERT_THAT(root, NotNull()); + auto maybe_removed = root->FindChild({}, "permission"); + ASSERT_THAT(maybe_removed, NotNull()); +} + } // namespace aapt diff --git a/tools/aapt2/java/AnnotationProcessor.cpp b/tools/aapt2/java/AnnotationProcessor.cpp index 8c644cf83339..a7f6f5524e21 100644 --- a/tools/aapt2/java/AnnotationProcessor.cpp +++ b/tools/aapt2/java/AnnotationProcessor.cpp @@ -64,29 +64,31 @@ static std::array<AnnotationRule, 3> sAnnotationRules = {{ {"@FlaggedApi", AnnotationRule::kFlaggedApi, "@android.annotation.FlaggedApi", true}, }}; -void AnnotationProcessor::AppendCommentLine(std::string comment) { +void AnnotationProcessor::AppendCommentLine(std::string comment, bool add_api_annotations) { static constexpr std::string_view sDeprecated = "@deprecated"; - // Treat deprecated specially, since we don't remove it from the source comment. - if (comment.find(sDeprecated) != std::string::npos) { - annotation_parameter_map_[AnnotationRule::kDeprecated] = ""; - } + if (add_api_annotations) { + // Treat deprecated specially, since we don't remove it from the source comment. + if (comment.find(sDeprecated) != std::string::npos) { + annotation_parameter_map_[AnnotationRule::kDeprecated] = ""; + } - for (const AnnotationRule& rule : sAnnotationRules) { - std::string::size_type idx = comment.find(rule.doc_str.data()); - if (idx != std::string::npos) { - // Captures all parameters associated with the specified annotation rule - // by matching the first pair of parentheses after the rule. - std::regex re(std::string(rule.doc_str).append(R"(\s*\((.+)\))")); - std::smatch match_result; - const bool is_match = std::regex_search(comment, match_result, re); - if (is_match && rule.preserve_params) { - annotation_parameter_map_[rule.bit_mask] = match_result[1].str(); - comment.erase(comment.begin() + match_result.position(), - comment.begin() + match_result.position() + match_result.length()); - } else { - annotation_parameter_map_[rule.bit_mask] = ""; - comment.erase(comment.begin() + idx, comment.begin() + idx + rule.doc_str.size()); + for (const AnnotationRule& rule : sAnnotationRules) { + std::string::size_type idx = comment.find(rule.doc_str.data()); + if (idx != std::string::npos) { + // Captures all parameters associated with the specified annotation rule + // by matching the first pair of parentheses after the rule. + std::regex re(std::string(rule.doc_str).append(R"(\s*\((.+)\))")); + std::smatch match_result; + const bool is_match = std::regex_search(comment, match_result, re); + if (is_match && rule.preserve_params) { + annotation_parameter_map_[rule.bit_mask] = match_result[1].str(); + comment.erase(comment.begin() + match_result.position(), + comment.begin() + match_result.position() + match_result.length()); + } else { + annotation_parameter_map_[rule.bit_mask] = ""; + comment.erase(comment.begin() + idx, comment.begin() + idx + rule.doc_str.size()); + } } } } @@ -109,12 +111,12 @@ void AnnotationProcessor::AppendCommentLine(std::string comment) { comment_ << "\n * " << std::move(comment); } -void AnnotationProcessor::AppendComment(StringPiece comment) { +void AnnotationProcessor::AppendComment(StringPiece comment, bool add_api_annotations) { // We need to process line by line to clean-up whitespace and append prefixes. for (StringPiece line : util::Tokenize(comment, '\n')) { line = util::TrimWhitespace(line); if (!line.empty()) { - AppendCommentLine(std::string(line)); + AppendCommentLine(std::string(line), add_api_annotations); } } } diff --git a/tools/aapt2/java/AnnotationProcessor.h b/tools/aapt2/java/AnnotationProcessor.h index db3437e3b5b1..2217ab35705a 100644 --- a/tools/aapt2/java/AnnotationProcessor.h +++ b/tools/aapt2/java/AnnotationProcessor.h @@ -60,7 +60,10 @@ class AnnotationProcessor { // Adds more comments. Resources can have value definitions for various configurations, and // each of the definitions may have comments that need to be processed. - void AppendComment(android::StringPiece comment); + // + // If add_api_annotations is false, annotations found in the comment (e.g., "@SystemApi") + // will NOT be converted to Java annotations. + void AppendComment(android::StringPiece comment, bool add_api_annotations = true); void AppendNewLine(); @@ -73,7 +76,7 @@ class AnnotationProcessor { bool has_comments_ = false; std::unordered_map<uint32_t, std::string> annotation_parameter_map_; - void AppendCommentLine(std::string line); + void AppendCommentLine(std::string line, bool add_api_annotations); }; } // namespace aapt diff --git a/tools/aapt2/java/AnnotationProcessor_test.cpp b/tools/aapt2/java/AnnotationProcessor_test.cpp index e98e96ba3bc3..e5eee34f451c 100644 --- a/tools/aapt2/java/AnnotationProcessor_test.cpp +++ b/tools/aapt2/java/AnnotationProcessor_test.cpp @@ -136,7 +136,28 @@ TEST(AnnotationProcessorTest, NotEmitSystemApiAnnotation) { EXPECT_THAT(annotations, HasSubstr("This is a system API")); } -TEST(AnnotationProcessor, ExtractsFirstSentence) { +TEST(AnnotationProcessorTest, DoNotAddApiAnnotations) { + AnnotationProcessor processor; + processor.AppendComment( + "@SystemApi This is a system API\n" + "@FlaggedApi This is a flagged API\n" + "@TestApi This is a test API\n" + "@deprecated Deprecate me\n", /*add_api_annotations=*/ + false); + + std::string annotations; + StringOutputStream out(&annotations); + Printer printer(&out); + processor.Print(&printer); + out.Flush(); + + EXPECT_THAT(annotations, Not(HasSubstr("@android.annotation.SystemApi"))); + EXPECT_THAT(annotations, Not(HasSubstr("@android.annotation.FlaggedApi"))); + EXPECT_THAT(annotations, Not(HasSubstr("@android.annotation.TestApi"))); + EXPECT_THAT(annotations, Not(HasSubstr("@Deprecated"))); +} + +TEST(AnnotationProcessorTest, ExtractsFirstSentence) { EXPECT_THAT(AnnotationProcessor::ExtractFirstSentence("This is the only sentence"), Eq("This is the only sentence")); EXPECT_THAT(AnnotationProcessor::ExtractFirstSentence( diff --git a/tools/aapt2/java/JavaClassGenerator.cpp b/tools/aapt2/java/JavaClassGenerator.cpp index 58f656458177..6e73b017cce2 100644 --- a/tools/aapt2/java/JavaClassGenerator.cpp +++ b/tools/aapt2/java/JavaClassGenerator.cpp @@ -180,7 +180,10 @@ static void AddAttributeFormatDoc(AnnotationProcessor* processor, Attribute* att << "<td>" << std::hex << symbol.value << std::dec << "</td>" << "<td>" << util::TrimWhitespace(symbol.symbol.GetComment()) << "</td></tr>"; - processor->AppendComment(line.str()); + // add_api_annotations is false since we don't want any annotations + // (e.g., "@deprecated")/ found in the enum/flag values to be propagated + // up to the attribute. + processor->AppendComment(line.str(), /*add_api_annotations=*/false); } processor->AppendComment("</table>"); } diff --git a/tools/aapt2/java/JavaClassGenerator_test.cpp b/tools/aapt2/java/JavaClassGenerator_test.cpp index 40395ed64fe3..bca9f4bc58c4 100644 --- a/tools/aapt2/java/JavaClassGenerator_test.cpp +++ b/tools/aapt2/java/JavaClassGenerator_test.cpp @@ -324,7 +324,58 @@ TEST(JavaClassGeneratorTest, CommentsForSimpleResourcesArePresent) { EXPECT_THAT(output, HasSubstr(expected_text)); } -TEST(JavaClassGeneratorTest, CommentsForEnumAndFlagAttributesArePresent) {} +TEST(JavaClassGeneratorTest, CommentsForEnumAndFlagAttributesArePresent) { + std::unique_ptr<Attribute> flagAttr = + test::AttributeBuilder() + .SetTypeMask(android::ResTable_map::TYPE_FLAGS) + .SetComment("Flag attribute") + .AddItemWithComment("flagOne", 0x01, "Flag comment 1") + .AddItemWithComment("flagTwo", 0x02, "@deprecated Flag comment 2") + .Build(); + std::unique_ptr<Attribute> enumAttr = + test::AttributeBuilder() + .SetTypeMask(android::ResTable_map::TYPE_ENUM) + .SetComment("Enum attribute") + .AddItemWithComment("enumOne", 0x01, "@TestApi Enum comment 1") + .AddItemWithComment("enumTwo", 0x02, "Enum comment 2") + .Build(); + + std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder() + .AddValue("android:attr/one", std::move(flagAttr)) + .AddValue("android:attr/two", std::move(enumAttr)) + .Build(); + + std::unique_ptr<IAaptContext> context = + test::ContextBuilder() + .AddSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get())) + .SetNameManglerPolicy(NameManglerPolicy{"android"}) + .Build(); + JavaClassGeneratorOptions options; + options.use_final = false; + JavaClassGenerator generator(context.get(), table.get(), options); + + std::string output; + StringOutputStream out(&output); + ASSERT_TRUE(generator.Generate("android", &out)); + out.Flush(); + + // Special annotations from the enum/flag values should NOT generate + // annotations for the attribute value. + EXPECT_THAT(output, Not(HasSubstr("@Deprecated"))); + EXPECT_THAT(output, Not(HasSubstr("@android.annotation.TestApi"))); + + EXPECT_THAT(output, HasSubstr("Flag attribute")); + EXPECT_THAT(output, HasSubstr("flagOne")); + EXPECT_THAT(output, HasSubstr("Flag comment 1")); + EXPECT_THAT(output, HasSubstr("flagTwo")); + EXPECT_THAT(output, HasSubstr("@deprecated Flag comment 2")); + + EXPECT_THAT(output, HasSubstr("Enum attribute")); + EXPECT_THAT(output, HasSubstr("enumOne")); + EXPECT_THAT(output, HasSubstr("@TestApi Enum comment 1")); + EXPECT_THAT(output, HasSubstr("enumTwo")); + EXPECT_THAT(output, HasSubstr("Enum comment 2")); +} TEST(JavaClassGeneratorTest, CommentsForStyleablesAndNestedAttributesArePresent) { Attribute attr; diff --git a/tools/aapt2/test/Builders.cpp b/tools/aapt2/test/Builders.cpp index 65f63dc68e54..b5934e40a2a3 100644 --- a/tools/aapt2/test/Builders.cpp +++ b/tools/aapt2/test/Builders.cpp @@ -177,12 +177,25 @@ AttributeBuilder& AttributeBuilder::SetWeak(bool weak) { return *this; } +AttributeBuilder& AttributeBuilder::SetComment(StringPiece comment) { + attr_->SetComment(comment); + return *this; +} + AttributeBuilder& AttributeBuilder::AddItem(StringPiece name, uint32_t value) { attr_->symbols.push_back( Attribute::Symbol{Reference(ResourceName({}, ResourceType::kId, name)), value}); return *this; } +AttributeBuilder& AttributeBuilder::AddItemWithComment(StringPiece name, uint32_t value, + StringPiece comment) { + Reference ref(ResourceName({}, ResourceType::kId, name)); + ref.SetComment(comment); + attr_->symbols.push_back(Attribute::Symbol{ref, value}); + return *this; +} + std::unique_ptr<Attribute> AttributeBuilder::Build() { return std::move(attr_); } diff --git a/tools/aapt2/test/Builders.h b/tools/aapt2/test/Builders.h index 098535d8526f..9ee44ba6d04c 100644 --- a/tools/aapt2/test/Builders.h +++ b/tools/aapt2/test/Builders.h @@ -116,7 +116,10 @@ class AttributeBuilder { AttributeBuilder(); AttributeBuilder& SetTypeMask(uint32_t typeMask); AttributeBuilder& SetWeak(bool weak); + AttributeBuilder& SetComment(android::StringPiece comment); AttributeBuilder& AddItem(android::StringPiece name, uint32_t value); + AttributeBuilder& AddItemWithComment(android::StringPiece name, uint32_t value, + android::StringPiece comment); std::unique_ptr<Attribute> Build(); private: |